js方法
基础
类型
typeof
返回值有六种可能: number
、string
、boolean
、object
、 function
、undefined
。
number
数字类型,在内部被表示为64位的浮点数,和java
的double
一样。不像大多数其他的编程语言,它没有分离出整数类型,所以1与1.0是相同的值。
还有两个特殊的数NaN
和Infinity
。
string
用于处理文本(字符串),和java
中的String
差不多,相关方法也很像,length
属性声明了该字符串中的字符数。
boolean
布尔值,表示两个值:true
或 false
。使用Boolean()函数时,0
、-0
、null
、""
、false
、undefined
、NaN
都为false
,否则为true
。
object
万物皆对象,JavaScript 提供多个内建对象,比如 Date
、Array
等等。 对象只是带有属性和方法的特殊数据类型。对象的统一空值null
。
function
JavaScript
函数,函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块,函数是对象,函数也有属性和方法。
undefined
属性用于存放JavaScript
的undefined
值。null
表示无值,而undefined
表示一个未声明的变量,或已声明但没有赋值的变量,或一个并不存在的对象属性。
逻辑运算符
&&
逻辑与 a && b
如果a的布尔值为false,则跳过b,直接返回a;
如果a的布尔值为true,则返回b;
使用:
- 用在if判断中。
- 判断方法执行,例如:当传入参数有值时执行初始化方法。
var a = false, b = true; function aFun() { console.log("aaa"); } a && aFun(); // 不执行方法,直接返回a的值,这里没有接收 b && aFun(); // 执行方法,打印aaa
||
逻辑或 a || b
如果a的布尔值为false,则返回b;
如果a的布尔值为true,则跳过b,直接返回a;
使用:
- 用在if判断中。
- 用在赋值语句中,例如:当传入参数为空时设置默认值。
var a = 0, b = 1, c; c = a || b; console.log(c); // 1 c = b || 3; console.log(c); // 3
!
取反
任何对象取反后都会转换为布尔值,获取自己本身的布尔值时可以取反两次例如!!
。
==和===
==
先比较类型,类型相同则比较值,类型不同,则转换为相同类型,再比较值。
一些容易出问题的逻辑:
console.log("0 == ''", 0 == ''); // true
console.log("0 == '0'", 0 == '0'); // true
console.log("0 == false", 0 == false); // true
console.log("0 == []", 0 == []); // true
console.log("0 == [0]", 0 == [0]); // true
console.log("0 == ['0']", 0 == ['0']); // true
console.log("1 == '1'", 1 == '1'); // true
console.log("1 == true", 1 == true); // true
console.log("1 == [1]", 1 == [1]); // true
console.log("1 == ['1']", 1 == ['1']); // true
console.log("null == undefined", null == undefined); // true
===
既比较类型也比较值。
一些容易出问题的逻辑:
console.log("0 === ''", 0 === ''); // false
console.log("0 === '0'", 0 === '0'); // false
console.log("1 === '1'", 1 === '1'); // false
console.log("null === undefined", null === undefined); // false
字符串
以下所有的str
对象初始化都为var str = 'ABCabcABC';
。
所有方法都不会改变原始字符串。
charAt(index)
返回在指定位置的字符。
str.charAt(2); // "C"
str.charAt(10); // ""
charCodeAt(index)
返回在指定的位置的字符的 Unicode 编码。
str.charCodeAt(2); // 67
str.charCodeAt(10); // NaN
concat(s1, s2, ..., sn)
连接两个或更多字符串,并返回新的字符串。
str.concat('Ss', 66, true); // "ABCabcABCSs66true"
indexOf(s)
返回某个指定的字符串值在字符串中首次出现的位置。
str.indexOf("A"); // 0
str.indexOf("D"); // -1
lastIndexOf(s)
从后向前搜索字符串,并从起始位置(0)开始计算返回字符串最后出现的位置。
str.lastIndexOf("A"); // 6
includes(s)
查找字符串中是否包含指定的子字符串。
str.includes("ABC"); // true
str.includes("ABCD"); // false
match(regexp)
查找找到一个或多个正则表达式的匹配。
str.match(/A.C/g); // ["ABC", "ABC"]
repeat(size)
复制字符串指定次数,并将它们连接在一起返回。
str.repeat(2); // "ABCabcABCABCabcABC"
replace(s/regexp, replacer)
在字符串中查找匹配的子串,并替换与正则表达式匹配的子串。第一个参数传字符串则只替换匹配到的第一个。
str.replace(/A.C/g, ""); // "abc"
str.replace("ABC", ""); // "abcABC"
search(searchvalue)
查找与正则表达式相匹配的值。于indexOf()差不多,但支持正则表达式。
str.search(/[a-z]/g); // 3
str.search("ABC"); // 0
split(separator,limit)
把一个字符串分割成字符串数组。
参数 | 描述 |
---|---|
separator | 可选。字符串或正则表达式,从该参数指定的地方分割。 |
limit | 可选。该参数可指定返回的数组的最大长度。如果设置了该参数,返回的子串不会多于这个参数指定的数组。如果没有设置该参数,整个字符串都会被分割,不考虑它的长度。 |
str.split("B"); // ["A", "CabcA", "C"]
str.split("B", 2); // ["A", "CabcA"]
str.split(/[b,B]/g); // ["A", "Ca", "cA", "C"]
startsWith(searchvalue, start)
用于检测字符串是否以指定的子字符串开始。
参数 | 描述 |
---|---|
searchvalue | 必需,要查找的字符串。 |
start | 可选,查找的开始位置,默认为 0。 |
str.startsWith("ABC"); // true
str.startsWith("abc"); // false
str.startsWith("abc", 3); // true
slice(start, end)
提取字符串的片断,并在新的字符串中返回被提取的部分。
参数 | 描述 |
---|---|
start | 必须。 要抽取的片断的起始下标,第一个字符位置为 0。如果为负数,则从尾部开始截取。 |
end | 可选。 紧接着要截取的片段结尾的下标。若未指定此参数,则要提取的子串包括 start 到原字符串结尾的字符串。如果该参数是负数,那么它规定的是从字符串的尾部开始算起的位置。slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。 |
str.slice(2); // "CabcABC"
str.slice(2, 4); // "Ca"
str.slice(-2); // "BC"
str.slice(-2, -1); // "B"
str.slice(-4, 8); // "cAB"
substring(from, to)
用于提取字符串中介于两个指定下标之间的字符。
返回的子串包括开始处的字符,但不包括结束处的字符。
参数 | 描述 |
---|---|
from | 必需。一个非负的整数,规定要提取的子串的第一个字符在 string Object 中的位置。 |
to | 可选。一个非负的整数,比要提取的子串的最后一个字符在 string Object 中的位置多 1。如果省略该参数,那么返回的子串会一直到字符串的结尾。 |
str.substring(2); // "CabcABC"
str.substring(2,4); // "Ca"
substr(start, length)
在字符串中抽取从开始下标开始的指定数目的字符。
参数 | 描述 |
---|---|
start | 必需。要抽取的子串的起始下标。必须是数值。如果是负数,那么该参数声明从字符串的尾部开始算起的位置。也就是说,-1 指字符串中最后一个字符,-2 指倒数第二个字符,以此类推。 |
length | 可选。子串中的字符数。必须是数值。如果省略了该参数,那么返回从 stringObject 的开始位置到结尾的字串。 |
str.substr(2); // "CabcABC"
str.substr(2,4); // "Cabc"
str.substr(-2); // "BC"
str.substr(-3, 1); // "A"
toLowerCase()
用于把字符串转换为小写。
str.toLowerCase(); // "abcabcabc"
toLowerCase()
用于把字符串转换为大写。
str.toUpperCase(); // "ABCABCABC"
trim()
用于删除字符串的头尾空白符,空白符包括:空格、制表符 tab、换行符等其他空白符等。
该方法不适用于null
,undefined
类型。
数组
concat(array2,array3,...,arrayX)
用于连接两个或多个数组。该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。
var nums = [0,1,2,3];
var strs = ["a","c","c"];
var res = nums.concat(strs);
console.log(res); // [0, 1, 2, 3, "a", "c", "c"]
res = nums.concat(strs, ["6", "6", "6"]);
console.log(res); // [0, 1, 2, 3, "a", "c", "c", "6", "6", "6"]
copyWithin(target, start, end)
用于从数组的指定位置拷贝元素到数组的另一个指定位置中。
会改变原始数组得值。
参数 | 描述 |
---|---|
target | 必需。复制到指定目标索引位置。 |
start | 可选。元素复制的起始位置。 |
end | 可选。停止复制的索引位置 (默认为 array.length)。如果为负值,表示倒数。 |
var nums = [0,1,2,3,4,5,6,7,8,9];
// 复制数组所有元素,从数组的第5个元素开始粘贴
console.log(nums.copyWithin(5)); // [0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
nums = [0,1,2,3,4,5,6,7,8,9];
// 复制从数组下标为2往后的元素,从数组的第5个元素开始粘贴
console.log(nums.copyWithin(5, 2)); // [0, 1, 2, 3, 4, 2, 3, 4, 5, 6]
nums = [0,1,2,3,4,5,6,7,8,9];
// 复制从数组下标为2到下标4的元素,从数组的第5个元素开始粘贴
console.log(nums.copyWithin(5, 2, 4)); // [0, 1, 2, 3, 4, 2, 3, 7, 8, 9]
fill(value, start, end)
用于将一个固定值替换数组的元素。
会改变原始数组。
参数 | 描述 |
---|---|
value | 必需。填充的值。 |
start | 可选。开始填充位置。 |
end | 可选。停止填充位置 (默认为 array.length) |
var nums = [0,1,2,3,4,5,6,7,8,9];
nums.fill(6);
console.log(nums); // [6, 6, 6, 6, 6, 6, 6, 6, 6, 6]
nums.fill(8, 3);
console.log(nums); // [6, 6, 6, 8, 8, 8, 8, 8, 8, 8]
nums.fill("9", 3, 6);
console.log(nums); // [6, 6, 6, "9", "9", "9", 8, 8, 8, 8]
includes(searchElement, fromIndex)
用来判断一个数组是否包含一个指定的值,如果是返回 true,否则false。
参数 | 描述 |
---|---|
searchElement | 必须。需要查找的元素值。 |
fromIndex | 可选。从该索引处开始查找 searchElement。如果为负值,则按升序从 array.length + fromIndex 的索引开始搜索。默认为 0。如果fromIndex 大于等于数组长度 ,则返回 false 。该数组不会被搜索。如果 fromIndex 为负值,如果计算出的索引小于 0,则整个数组都会被搜索。 |
var nums = [0,1,2,3,4,5,6,7,8,9];
console.log(nums.includes(5)); // true
console.log(nums.includes(10)); // false
console.log(nums.includes(5, 3)); // true
console.log(nums.includes(5, 6)); // false
console.log(nums.includes(5, -5)); // true
console.log(nums.includes(5, -1)); // false
indexOf(item,start)
返回数组中某个指定的元素位置。如果要检索的元素没有出现,则该方法返回 -1。
参数 | 描述 |
---|---|
item | 必须。查找的元素。 |
start | 可选的整数参数。规定在数组中开始检索的位置。它的合法取值是 0 到 stringObject.length - 1。如省略该参数,则将从字符串的首字符开始检索。 |
var nums = ["0","1","2","3","4","5","6","7","8","9"];
console.log(nums.indexOf("5")); // 5
console.log(nums.indexOf("10")); // -1
console.log(nums.indexOf("5", 3)); // 5
console.log(nums.indexOf("5", 6)); // -1
lastIndexOf(item,start)
返回数组中某个指定的元素位置。从该字符串的后面向前查找。如果要检索的元素没有出现,则该方法返回 -1。
参数 | 描述 |
---|---|
item | 必须。查找的元素。 |
start | 可选的整数参数。规定在字符串中开始检索的位置。它的合法取值是 0 到 stringObject.length - 1。如省略该参数,则将从字符串的最后一个字符处开始检索。 |
var nums = ["0","1","2","3","4","3","2","1","0"];
console.log(nums.lastIndexOf("3")); // 5
console.log(nums.lastIndexOf("5")); // -1
console.log(nums.lastIndexOf("3", 4)); // 3
console.log(nums.lastIndexOf("3", 6)); // 5
join(separator)
用于把数组中的所有元素转换一个字符串。
参数 | 描述 |
---|---|
separator | 可选。指定要使用的分隔符。如果省略该参数,则使用逗号作为分隔符。 |
var nums = [0,1,2,3,4,5,6,7,8,9];
console.log(nums.join()); // "0,1,2,3,4,5,6,7,8,9"
console.log(nums.join("")); // "0123456789"
console.log(nums.join("|")); // "0|1|2|3|4|5|6|7|8|9"
shift()
用于删除数组的第一个元素并返回删除的元素。
var arr = ["A", "B", "C"];
console.log(arr.shift()); // "A"
console.log(arr); // ["B", "C"]
pop()
用于删除数组的最后一个元素并返回删除的元素。
var arr = ["A", "B", "C"];
console.log(arr.pop()); // "C"
console.log(arr); // ["A", "B"]
splice(index,howmany,item1,.....,itemX)
用于添加或删除数组中的元素。
参数 | 描述 |
---|---|
index | 必需。规定从何处添加/删除元素。该参数是开始插入和(或)删除的数组元素的下标,必须是数字。 |
howmany | 可选。规定应该删除多少元素。必须是数字,但可以是 "0"。如果未规定此参数,则删除从 index 开始到原数组结尾的所有元素。 |
item1, ..., itemX | 可选。要添加到数组的新元素 |
var arr = ["A", "B", "C", "D", "E"];
console.log(arr.splice(3)); // ["D", "E"]
console.log(arr); // ["A", "B", "C"]
console.log(arr.splice(1, 1)); // ["B"]
console.log(arr); // ["A", "C"]
console.log(arr.splice(1, 0, "X")); // []
console.log(arr); // ["A", "X", "C"]
console.log(arr.splice(2, 1, "X")); // ["C"]
console.log(arr); // ["A", "X", "X"]
push(item1, item2, ..., itemX)
向数组的末尾添加一个或多个元素,并返回新的长度。
var arr = ["A", "B", "C"];
console.log(arr.push("D")); // 4
console.log(arr); // ["A", "B", "C", "D"]
console.log(arr.push("E", 6, true)); // 7
console.log(arr); // ["A", "B", "C", "D", "E", 6, true]
unshift(item1, item2, ..., itemX)
向数组的开头添加一个或更多元素,并返回新的长度。
var arr = ["A", "B", "C"];
console.log(arr.unshift("D")); // 4
console.log(arr); // ["D", "A", "B", "C"]
console.log(arr.unshift("E", 6, true)); // 7
console.log(arr); // ["E", 6, true, "D", "A", "B", "C"]
reverse()
用于反转数组中元素的顺序。
var arr = ["A", "B", "C"];
console.log(arr.reverse()); // ["C", "B", "A"]
console.log(arr); // ["C", "B", "A"]
slice(start, end)
从已有的数组中返回选定的元素。不会改变原始数组。
var nums = [0,1,2,3,4,5,6,7,8,9];
console.log(nums.slice()); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(nums.slice(5)); // [5, 6, 7, 8, 9]
console.log(nums.slice(5, 8)); // [5, 6, 7]
console.log(nums.slice(-3)); // [7, 8, 9]
console.log(nums.slice(-3, -1)); // [7, 8]
sort(sortfunction)
用于对数组的元素进行排序。
默认排序顺序为按字母升序。
参数 | 描述 |
---|---|
sortfunction | 可选。规定排序顺序。必须是函数。 |
var nums = [40,100,1,5,25,10];
// 默认转换为字符串排序
nums.sort();
console.log(nums); // [1, 10, 100, 25, 40, 5]
// 数字升序
nums.sort(function(a,b){
return a-b;
});
console.log(nums); // [1, 5, 10, 25, 40, 100]
// 数字降序
nums.sort(function(a,b){
return b-a;
});
console.log(nums); // [100, 40, 25, 10, 5, 1]
every(function(currentValue,index,arr), thisValue)
用于检测数组所有元素是否都符合指定条件(通过函数提供)。
如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
如果所有元素都满足条件,则返回 true。
该方法不会对空数组进行检测。不会改变原始数组。
参数 | 描述 | ||||||||
---|---|---|---|---|---|---|---|---|---|
function(currentValue, index,arr) | 必须。函数,数组中的每个元素都会执行这个函数。
| ||||||||
thisValue | 可选。对象作为该执行回调时使用,传递给函数,用作 "this" 的值。如果省略了 thisValue ,"this" 的值为 "undefined" |
var nums = [0,1,2,3,4,5,6,7,8,9], res;
// 判断数组中的数是否都大于5
res = nums.every(function(currentValue,index,arr) {
return currentValue > 5;
});
console.log(res); // false
// 判断数组中的数是否都小于10
res = nums.every(function(currentValue,index,arr) {
return currentValue < 10;
});
console.log(res); // true
some(function(currentValue,index,arr), thisValue)
用于检测数组中的元素是否满足指定条件(函数提供)。
如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。
如果没有满足条件的元素,则返回false。
该方法不会对空数组进行检测。不会改变原始数组。
var nums = [0,1,2,3,4,5,6,7,8,9], res;
// 判断数组中是否存在大于5的数
res = nums.some(function(currentValue,index,arr) {
return currentValue > 5;
});
console.log(res); // true
// 判断数组中是否存在大于10的数
res = nums.some(function(currentValue,index,arr) {
return currentValue > 10;
});
console.log(res); // false
filter(function(currentValue,index,arr), thisValue)
创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
不会对空数组进行检测。不会改变原始数组。
var nums = [0,1,2,2,2,3,4,2,5,0,6,7,8,9], res;
// 获取数组中大于5的值
res = nums.filter(function(currentValue,index,arr) {
return currentValue > 5;
});
console.log(res); // [6, 7, 8, 9]
// 对数组元素进行去重
res = nums.filter(function(currentValue,index,arr) {
//当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
return arr.indexOf(currentValue) === index;
});
console.log(res); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
find(function(currentValue,index,arr), thisValue)
返回通过测试(函数内判断)的数组的第一个元素的值。
对于空数组,函数是不会执行的。并没有改变数组的原始值。
var objArr = [
{id: 1, name: "A"},
{id: 2, name: "B"},
{id: 3, name: "C"}
], res;
// 获取数组中name值为C的元素
res = objArr.find(function(currentValue, index, arr){
return currentValue.name === "C";
});
console.log(res); // {id: 3, name: "C"}
// 获取数组中id值为大于1的元素
res = objArr.find(function(currentValue, index, arr){
return currentValue.id > 1;
});
console.log(res); // {id: 2, name: "B"}
findIndex(function(currentValue,index,arr), thisValue)
返回通过测试(函数内判断)的数组的第一个元素的位置。
对于空数组,函数是不会执行的。并没有改变数组的原始值。
var objArr = [
{id: 1, name: "A"},
{id: 2, name: "B"},
{id: 3, name: "C"}
], res;
// 获取数组中name值为C的元素下标
res = objArr.findIndex(function(currentValue, index, arr){
return currentValue.name === "C";
});
console.log(res); // 2
// 获取数组中id值为大于1的元素下标
res = objArr.findIndex(function(currentValue, index, arr){
return currentValue.id > 1;
});
console.log(res); // 1
forEach(function(currentValue,index,arr), thisValue)
用于调用数组的每个元素,并将元素传递给回调函数。
对于空数组,函数是不会执行的。
forEach()
本身是不支持的continue
与break
语句的,continue
可以使用return
代替,break
还是建议使用for
循环语句实现。
var nums = [0,1,2,3,4,5,6,7,8,9], res = 0;
// 获取数组中name值为C的元素下标
nums.forEach(function(currentValue, index, arr) {
res += currentValue;
});
console.log(res); // 45
map(function(currentValue,index,arr), thisValue)
返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。按照原始数组元素顺序依次处理元素。
对于空数组,函数是不会执行的。不会改变原始数组。
var objArr = [
{id: 1, name: "A"},
{id: 2, name: "B"},
{id: 3, name: "C"}
], res;
// 获取对象中的id列表
res = objArr.map(function(currentValue, index, arr) {
return currentValue.id;
});
console.log(res); // [1, 2, 3]
reduce(function(total, currentValue, index, arr), initialValue)
接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
该方法不会对空数组进行检测。
参数 | 描述 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
function(total, currentValue, index, arr) | 必须。函数,数组中的每个元素都会执行这个函数。
| ||||||||||
thisValue | 可选。对象作为该执行回调时使用,传递给函数,用作 "this" 的值。如果省略了 thisValue ,"this" 的值为 "undefined" |
var nums = [0,1,2,3,4,5,6,7,8,9];
// 求和
var res = nums.reduce(function(total,currentValue,index,arr) {
return total + currentValue;
});
console.log(res); // 45
reduceRight(function(total, currentValue, index, arr), initialValue)
该方法的功能和reduce()
功能是一样的,不同的是reduceRight()
从数组的末尾向前将数组中的数组项做累加。
参数描述同上
var nums = [0,1,2,3,4,5,6,7,8,9];
// 求和
var res = nums.reduceRight(function(total,currentValue,index,arr) {
return total + '' + currentValue;
});
console.log(res); // 9876543210
ERROR
try {
throw new Error("抛个异常");
} catch(err) {
console.error(err.name, err.message);
// Error 抛个异常
} finally {
console.log("finally");
}
静态方法
String.fromCharCode(n1, n2, ..., nX)
可接受一个或多个指定的Unicode
值,然后返回一个字符串。
String.fromCharCode(72,69,76,76,79); // "HELLO"
String.fromCharCode(97); // "a"
String.fromCharCode(49); // "1"
Array.isArray(obj)
用于判断一个对象是否为数组。
Array.isArray([]); // true
Array.isArray([1,2,3]); // true
Array.isArray(null); // false
Array.isArray(""); // false
Array.isArray({}); // false
JSON.parse(text, function(key, value))
将json字符串
转换为JavaScript
对象。
参数 | 描述 |
---|---|
text | 必需, 一个有效的 JSON 字符串。 |
function(key, value) | 可选,一个转换结果的函数, 将为对象的每个成员调用此函数。参数有key和value,return value;为转换后key值对应的值。 |
var obj = JSON.parse("{\"a\":1,\"b\":2}");
console.log(obj); // {a: 1, b: 2}
var obj = JSON.parse("{\"a\":1,\"b\":2}", function(key, value) {
console.log("key:" + key, value);
if (key) {
return value + 6;
}
return value;
});
console.log(obj);
/*
key:a 1
key:b 2
key: {a: 7, b: 8}
{a: 7, b: 8}
*/
JSON.stringify(value, function(key, value)/replacer, space)
将JavaScript
对象转换为json字符串
。
参数 | 描述 |
---|---|
value | 必需, 要转换的JavaScript 值(通常为对象或数组)。 |
function(key, value)/replacer | 可选,一个转换结果的函数, 将为对象的每个成员调用此函数。参数有key和value,return value;为转换后key值对应的值。 |
text | 可选,文本添加缩进、空格和换行符,如果 space 是一个数字,则返回值文本在每个级别缩进指定数目的空格,如果 space 大于 10,则文本缩进 10 个空格。space 也可以使用非数字,如:\t。 |
var obj = {a: 1, b: 2}, res;
console.log(JSON.stringify(obj)); // {"a":1,"b":2}
res = JSON.stringify(obj, function(key, value) {
console.log("key:" + key, value);
if (key) {
return value + 10;
}
return value;
});
console.log(res);
/*
key: {a: 1, b: 2}
key:a 1
key:b 2
{"a":11,"b":12}
*/
res = JSON.stringify(obj, ["a"]);
console.log(res); // {"a":7}
res = JSON.stringify(obj, null, 1);
console.log(res);
/*
{
"a": 7,
"b": 8
}
*/
res = JSON.stringify(obj, null, 8);
console.log(res);
/*
{
"a": 1,
"b": 2
}
*/
res = JSON.stringify(obj, null, '*-* ');
console.log(res);
/*
{
*-* "a": 1,
*-* "b": 2
}
*/
Object.assign(target, source1, source2, ... ,sourceN);
用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象,如果属性相同,以最后一个为准。
var target = { a: 1, b: 2 };
var source = { b: 4, c: 5 };
var returnedTarget = Object.assign(target, source);
console.log(target); // {a: 1, b: 4, c: 5}
console.log(returnedTarget); // {a: 1, b: 4, c: 5}
returnedTarget = Object.assign({}, {s: 666}, source);
console.log(returnedTarget); // {a: 1, b: 4, c: 5}
Object.create(proto,propertiesObject)
方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。
参数 | 描述 |
---|---|
proto | 新创建对象的原型对象。 |
propertiesObject | 可选。需要传入一个对象,该对象的属性类型参照Object.defineProperties()的第二个参数。如果该参数被指定且不为 undefined,该传入对象的自有可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)将为新创建的对象添加指定的属性值和对应的属性描述符。 |
var obj;
// 创建一个原型为null的空对象
obj = Object.create(null);
console.log(obj); // {}
console.log(obj.__proto__); // undefined
// 以字面量方式创建的空对象就相当于: obj = {};
obj = Object.create(Object.prototype);
console.log(obj); // {}
console.log(obj.__proto__); // {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
// 以{a: 66}为原型创建新对象
obj = Object.create({a: 66});
console.log(obj); // {}
console.log(obj.a); // 66
console.log(obj.__proto__); // {a: 66}
// 创建一个以另一个空对象为原型,且拥有一个属性p的对象
obj = Object.create({}, { p: { value: 42 } });
console.log(obj); // {p: 42}
// 省略了的属性特性默认为false,所以属性p是不可写,不可枚举,不可配置的
obj.p = 24;
console.log(obj.p); // 42
//创建一个可写的,可枚举的,可配置的属性p
o2 = Object.create({}, {
p: {
value: 42,
writable: true, // 当 writable 属性设置为 false 时,该属性被称为“不可写的”。它不能被重新赋值。
enumerable: true, // enumerable 定义了对象的属性是否可以在 for...in 循环和 Object.keys() 中被枚举。
configurable: true // configurable 特性表示对象的属性是否可以被删除,以及除 value 和 writable 特性外的其他特性是否可以被修改。
}
});
Object.defineProperty(obj, prop, descriptor)
直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
参数 | 描述 |
---|---|
obj | 必需,要定义属性的对象。 |
prop | 必需,要定义或修改的属性的名称或 Symbol 。 |
descriptor | 必需,要定义或修改的属性描述符。 |
descriptor属性
参数 | 默认值 | 描述 |
---|---|---|
configurable | false | 当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。 |
enumerable | false | 当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。 |
value | undefined | 该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。 |
writable | false | 当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符改变。 |
get | undefined | 属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。 |
set | undefined | 属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。 |
var o = {};
o.a = 1;
// 等同于:
Object.defineProperty(o, "a", {
value: 1,
writable: true,
configurable: true,
enumerable: true
});
Object.defineProperty(o, "a", { value : 1 });
// 等同于:
Object.defineProperty(o, "a", {
value: 1,
writable: false,
configurable: false,
enumerable: false
});
// configurable: false 这时在修改descriptor中的值就会报错了
Object.defineProperty(o, 'a', {
configurable: true
}); // throws a TypeError
// get/set和value/writable不能同时出现
var obj = Object.defineProperty(o, "b", {
get: function() {
console.log('get!');
// 这里不能直接调用 this.b 会陷入死循环
return this._b;
},
set: function(value) {
console.log('set!');
this._b = value;
}
});
Object.defineProperties(obj, props)
在一个对象上定义新的属性或修改现有属性,并返回该对象。
参数 | 描述 |
---|---|
obj | 必需,在其上定义或修改属性的对象。 |
props | 必需,要定义其可枚举属性或修改的属性描述符的对象。对象中存在的属性描述符主要有两种:数据描述符和访问器描述符(更多详情,请参阅Object.defineProperty())。描述符具有以下键: |
var obj = {};
Object.defineProperties(obj, {
'property1': {
value: true,
writable: true,
configurable: true,
enumerable: true
},
'property2': {
value: 'Hello'
}
});
console.log(obj); // {property1: true, property2: "Hello"}
console.log(Object.keys(obj)); // ["property1"]
Object.entries(obj)
返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)。
var obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]
// 会根据key值自动排序
var anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.entries(anObj)); // [ ['2', 'b'], ['7', 'c'], ['100', 'a'] ]
// getFoo是不可枚举的属性
var myObj = Object.create({}, {
getFoo: {
value() { return this.foo; }
}
});
myObj.foo = 'bar';
console.log(Object.entries(myObj)); // [ ['foo', 'bar'] ]
// 非对象参数将被强制转换为对象
console.log(Object.entries('foo')); // [ ['0', 'f'], ['1', 'o'], ['2', 'o'] ]
// 遍历key-value
var obj = { a: 5, b: 7, c: 9 };
for (var [key, value] of Object.entries(obj)) {
console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
}
Object.freeze(obj)
冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze()
返回和传入的参数相同的对象。
var obj = {
prop: function() {},
foo: 'bar'
};
// 新的属性会被添加, 已存在的属性可能
// 会被修改或移除
obj.foo = 'baz';
obj.lumpy = 'woof';
delete obj.prop;
// 作为参数传递的对象与返回的对象都被冻结
// 所以不必保存返回的对象(因为两个对象全等)
var o = Object.freeze(obj);
o === obj; // true
Object.isFrozen(obj); // === true
// 现在任何改变都会失效
obj.foo = 'quux'; // 静默地不做任何事
// 静默地不添加此属性
obj.quaxxor = 'the friendly duck';
// 在严格模式,如此行为将抛出 TypeErrors
function fail(){
'use strict';
obj.foo = 'sparky'; // throws a TypeError
delete obj.quaxxor; // 返回true,因为quaxxor属性从来未被添加
obj.sparky = 'arf'; // throws a TypeError
}
fail();
// 试图通过 Object.defineProperty 更改属性
// 下面两个语句都会抛出 TypeError.
Object.defineProperty(obj, 'ohai', { value: 17 });
Object.defineProperty(obj, 'foo', { value: 'eit' });
Object.isFrozen(obj)
判断一个对象是否被冻结。
// 一个对象默认是可扩展的,所以它也是非冻结的.
Object.isFrozen({}); // false
// 一个非空对象默认也是非冻结的.
var oneProp = { p: 42 };
Object.isFrozen(oneProp) // false
Object.preventExtensions(oneProp);
Object.defineProperty(oneProp, "p", { writable: false }); // 变得不可写
Object.defineProperty(oneProp, "p", { configurable: false }); // 变得不可配置
Object.isFrozen(oneProp) // true
// 数组为冻结的
Object.isFrozen(1); // true
// 字符串为冻结的
Object.isFrozen("str"); // true
Object.isFrozen(Object.freeze({})); // true
Object.preventExtensions(obj)
让一个对象变的不可扩展,也就是永远不能再添加新的属性。
// 使用Object.defineProperty方法为一个不可扩展的对象添加新属性会抛出异常.
var nonExtensible = { removable: true };
Object.preventExtensions(nonExtensible);
Object.defineProperty(nonExtensible, "new", { value: 8675309 }); // 抛出TypeError异常
// 在严格模式中,为一个不可扩展对象的新属性赋值会抛出TypeError异常.
function fail() {
"use strict";
nonExtensible.newProperty = "FAIL"; // throws a TypeError
}
fail();
Object.isExtensible(obj)
判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。
// 新对象默认是可扩展的.
var empty = {};
Object.isExtensible(empty); // true
// ...可以变的不可扩展.
Object.preventExtensions(empty);
Object.isExtensible(empty); // false
// 密封对象是不可扩展的.
var sealed = Object.seal({});
Object.isExtensible(sealed); // false
// 冻结对象也是不可扩展.
var frozen = Object.freeze({});
Object.isExtensible(frozen); // false
Object.seal(obj)
封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变。
var obj = {
prop: function() {},
foo: 'bar'
};
var o = Object.seal(obj);
o === obj; // true
Object.isSealed(obj); // true
// 仍然可以修改密封对象的属性值
obj.foo = 'quux';
// 但是你不能将属性重新定义成为访问器属性
Object.defineProperty(obj, 'foo', {
get: function() { return 'g'; }
}); // throws a TypeError
// 除了属性值以外的任何变化,都会失败.
obj.quaxxor = 'the friendly duck';
// 添加属性将会失败
delete obj.foo;
// 删除属性将会失败
// 通过Object.defineProperty添加属性将会报错
Object.defineProperty(obj, 'ohai', {
value: 17
}); // throws a TypeError
Object.defineProperty(obj, 'foo', {
value: 'eit'
}); // 通过Object.defineProperty修改属性值
Object.isSealed(obj)
判断一个对象是否被密封。
// 新建的对象默认不是密封的.
var empty = {};
Object.isSealed(empty); // false
// 如果你把一个空对象变的不可扩展,则它同时也会变成个密封对象.
Object.preventExtensions(empty);
Object.isSealed(empty); // true
var sealed = {};
Object.seal(sealed);
Object.isSealed(sealed); // true
// 一个密封对象同时也是不可扩展的.
Object.isExtensible(sealed); // === false
Object.getOwnPropertyDescriptor(obj, prop)
指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)
参数 | 描述 |
---|---|
obj | 必需,需要查找的目标对象 |
prop | 必需,目标对象内属性名称 |
var o, d;
o = { get foo() { return 17; } };
d = Object.getOwnPropertyDescriptor(o, "foo");
// d {
// configurable: true,
// enumerable: true,
// get: /*the getter function*/,
// set: undefined
// }
o = { bar: 42 };
d = Object.getOwnPropertyDescriptor(o, "bar");
// d {
// configurable: true,
// enumerable: true,
// value: 42,
// writable: true
// }
o = {};
Object.defineProperty(o, "baz", {
value: 8675309,
writable: false,
enumerable: false
});
d = Object.getOwnPropertyDescriptor(o, "baz");
// d {
// value: 8675309,
// writable: false,
// enumerable: false,
// configurable: false
// }
Object.getOwnPropertyNames(obj)
返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。
var arr = ["a", "b", "c"];
console.log(Object.getOwnPropertyNames(arr).sort()); // ["0", "1", "2", "length"]
// 类数组对象
var obj = { 0: "a", 1: "b", 2: "c"};
console.log(Object.getOwnPropertyNames(obj).sort()); // ["0", "1", "2"]
// 使用Array.forEach输出属性名和属性值
Object.getOwnPropertyNames(obj).forEach(function(val, idx, array) {
console.log(val + " -> " + obj[val]);
});
// 输出
// 0 -> a
// 1 -> b
// 2 -> c
//不可枚举属性
var my_obj = Object.create({}, {
getFoo: {
value: function() { return this.foo; },
enumerable: false
}
});
my_obj.foo = 1;
console.log(Object.getOwnPropertyNames(my_obj)); // ["getFoo", "foo"]
Object.getPrototypeOf(obj)
返回指定对象的原型(内部[[Prototype]]属性的值)。
var proto = {};
var obj = Object.create(proto);
Object.getPrototypeOf(obj) === proto; // true
Object.getPrototypeOf(/a/) === RegExp.prototype; // true
Object.getPrototypeOf("str") === String.prototype; // true
Object.setPrototypeOf(obj, prototype)
设置一个指定的对象的原型 ( 即, 内部[[Prototype]]属性)到另一个对象或null
。
Object.setPrototypeOf({}, null);
Object.setPrototypeOf({}, {a: 1});
Object.is(value1, value2)
判断两个值是否为同一个值。
console.log(Object.is('foo', 'foo')); // true
console.log(Object.is('foo', 'fo')); // false
console.log(Object.is([], [])); // false
var foo = { a: 1 };
var bar = foo;
console.log(Object.is(foo, bar )); // true
console.log(Object.is(foo, { a: 1 })); // false
console.log(Object.is(null, null)); // true
// 特例
console.log(Object.is(0, -0)); // false
console.log(Object.is(0, +0)); // true
console.log(Object.is(-0, -0)); // true
console.log(Object.is(NaN, 0/0)); // true
Object.keys(obj)
返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致 。
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // ['0', '1', '2']
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // ['0', '1', '2']
var anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(anObj)); // ['2', '7', '100']
var myObj = Object.create({}, {
getFoo: {
value: function () { return this.foo; }
}
});
myObj.foo = 1;
console.log(Object.keys(myObj)); // ['foo']
Object.values(obj)
返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用for...in
循环的顺序相同(区别在于for-in
循环枚举原型链中的属性)。
var obj = { foo: 'bar', baz: 42 };
console.log(Object.values(obj)); // ['bar', 42]
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.values(obj)); // ['a', 'b', 'c']
var an_obj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.values(an_obj)); // ['b', 'c', 'a']
var my_obj = Object.create({}, { getFoo: { value: function() { return this.foo; } } });
my_obj.foo = 'bar';
console.log(Object.values(my_obj)); // ['bar']
console.log(Object.values('foo')); // ['f', 'o', 'o']
全局函数
encodeURI(uri)
可把字符串作为URI
进行编码。对以下在URI
中具有特殊含义的ASCII
标点符号,encodeURI()
函数是不会进行转义的:,
/
?
:
@
&
=
+
$
#
(可以使用encodeURIComponent()
方法分别对特殊含义的 ASCII 标点符号进行编码。).
encodeURIComponent(uri)
可把字符串作为 URI 组件进行编码。该方法不会对ASCII
字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: -
_
.
!
~
*
'
(
)
。
decodeURI(uri)
可对encodeURI()
函数编码过的URI
进行解码。
decodeURIComponent(uri)
可对encodeURIComponent()
函数编码的URI
进行解码。
escape(string)
可对字符串进行编码,这样就可以在所有的计算机上读取该字符串。该方法不会对 ASCII 字母和数字进行编码,也不会对下面这些 ASCII 标点符号进行编码: *
@
-
_
+
.
/
。其他所有的字符都会被转义序列替换。
unescape(string)
可对通过escape()
编码的字符串进行解码。
isNaN(value)
isNaN() 函数用于检查其参数是否是非数字值。
如果参数值为 NaN 或字符串、对象、undefined等非数字值则返回 true, 否则返回 false。
Number(object)
把对象的值转换为数字。
如果对象的值无法转换为数字,那么Number()
函数返回NaN
。
parseFloat(string)
可解析一个字符串,并返回一个浮点数。
该函数指定字符串中的首个字符是否是数字。如果是,则对字符串进行解析,直到到达数字的末端为止,然后以数字返回该数字,而不是作为字符串。
console.log(parseFloat("10")); // 10
console.log(parseFloat("10.33")); // 10.33
console.log(parseFloat("34 45 66")); // 34
console.log(parseFloat(" 60 ")); // 60
console.log(parseFloat("40 years")); // 40
console.log(parseFloat("He was 40")); // NaN
parseInt(string, radix)
可解析一个字符串,并返回一个整数。
当参数radix
的值为0
,或没有设置该参数时,parseInt()
会根据string
来判断数字的基数。
默认数字的基数如下:
- 如果 string 以 "0x" 开头,parseInt() 会把 string 的其余部分解析为十六进制的整数。
- 如果 string 以 0 开头,那么 ECMAScript v3 允许 parseInt() 的一个实现把其后的字符解析为八进制或十六进制的数字。
- 如果 string 以 1 ~ 9 的数字开头,parseInt() 将把它解析为十进制的整数。
参数 | 描述 |
---|---|
string | 必需。要被解析的字符串。 |
radix | 可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。 |
console.log(parseInt("10")); // 10
console.log(parseInt("10.33")); // 10
console.log(parseInt("34 45 66")); // 34
console.log(parseInt(" 60 ")); // 60
console.log(parseInt("40 years")); // 40
console.log(parseInt("He was 40")); // NaN
console.log(parseInt("10", 10)); // 10
console.log(parseInt("010")); // 10
console.log(parseInt("0xa")); // 10
console.log(parseInt("00001010", 2)); // 10
String(object)
把对象的值转换为字符串
eval(string)
计算JavaScript
字符串,并把它作为脚本代码来执行。
如果参数是一个表达式,eval()
函数将执行表达式。如果参数是Javascript语句
,eval()将执行Javascript语句
。
eval()
是一个危险的函数,它使用与调用者相同的权限执行代码,所以尽可能的不要去使用它,以防被其他人员植入恶意代码。
eval("console.log('666')"); // 666
eval("function print(str) { console.log(str);}");
print("哈哈哈"); // 哈哈哈
var res = eval("1 + 2 + 3");
print(res ); // 6
function
Function
函数对象
每个JavaScript
函数实际上都是一个Function
对象。运行(function(){}).constructor === Function // true
便可以得到这个结论。
构造函数
new Function ([arg1[, arg2[, ...argN]],] functionBody)
参数 | 描述 |
---|---|
arg1, arg2, ... argN | 被函数使用的参数的名称必须是合法命名的。参数名称是一个有效的JavaScript标识符的字符串,或者一个用逗号分隔的有效字符串的列表;例如“×”,“theValue”,或“a,b”。 |
functionBody | 一个含有包括函数定义的 JavaScript 语句的字符串。 |
var sout = new Function("v", "console.log(v)");
sout(666); // 666
var sum = new Function('a', 'b,c', 'return a + b + c');
sout(sum(1,2,3)); // 6
关键字function
定义函数。
函数声明
function sout(v) {
console.log(v);
}
sout(666);
函数表达式
var sout = function (v) {
console.log(v);
};
sout(666);
自调用函数
函数表达式可以"自调用"。
自调用表达式会自动调用。
如果表达式后面紧跟 () ,则会自动调用。
不能自调用声明的函数。
通过添加括号,来说明它是一个函数表达式:
(function () {
console.log(666);
})();
自调用函数同样可以传参:
(function (v) {
console.log(v);
})(666);
还可以嵌套多层调用,不过需要控制()
数量,以及返回的函数数量:
(function (v) {
console.log(v);
return function (x) {
console.log(x);
return function () {
console.log("最后一层");
};
};
})(666)("我是x")();
看着有点饶,其实也很好理解,就是函数的返回值还是一个函数。
箭头函数
ES6 新增了箭头函数。
箭头函数表达式的语法比普通函数表达式更简洁。
(参数1, 参数2, …, 参数N) => { 函数声明 }
(参数1, 参数2, …, 参数N) => 表达式(单一)
// 相当于:(参数1, 参数2, …, 参数N) =>{ return 表达式; }
当只有一个参数时,圆括号是可选的:
(单一参数) => {函数声明}
单一参数 => {函数声明}
没有参数的函数应该写成一对圆括号:
() => {函数声明}
实例:
const sout = v => {console.log(v)};
sout(666); // 666
const sum = (a, b) => a + b;
sout(sum(3,3)); // 6
const noParam = () => {console.log("noParam ")};
noParam(); // noParam
参数
JavaScript
函数定义显式参数时没有指定数据类型。
JavaScript
函数对隐式参数没有进行类型检测。
JavaScript
函数对隐式参数的个数没有进行检测。
参数默认值为:undefined
。
显式参数(Parameters)
函数显式参数在函数定义时列出。
function sout(v) {
console.log(v)
}
sout(666); // 666
sout(); // undefined
// 如果你不想他打印undefined,而是打印空字符串可以这样,使用 ||
function sout(v) {
v = v || "";
console.log(v)
}
sout(666); // 666
sout(); //
// ES6 支持函数带有默认参数,可以这样写:
function sout(v = "") {
console.log(v)
}
sout(666); // 666
sout(); //
隐式参数(Arguments)
函数隐式参数在函数调用时传递给函数真正的值。
JavaScript
函数有个内置的对象arguments
对象。
argument
对象包含了函数调用的参数数组。
通过这种方式你可以很方便的获取所有参数的值:
function sum() {
console.log("当前函数传了", arguments.length,"个参数");
var total = 0;
for (var i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
}
console.log(sum()); // 0
console.log(sum(1,2,3,4,5,6,7,8,9)); // 45
function
方法
function.call(thisArg, arg1, arg2, ...)
使用一个指定的this
值和单独给出的一个或多个参数来调用一个函数。
参数 | 描述 |
---|---|
thisArg | 可选的。在function 函数运行时使用的this 值。请注意,this 可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为null 或undefined 时会自动替换为指向全局对象,原始值会被包装。 |
arg1, arg2, ... | 可选的。指定的参数列表。 |
function sout(x, y) {
console.log(this.name, x, y);
}
var name = "全局name";
sout.call(); // 全局name undefined undefined
sout.call({name: "我是name"}); // 我是name undefined undefined
sout.call({name: "我是name"}, "666", 888); // 我是name 666 888
sout.call(null, "666", 888); // 全局name 666 888
function.apply(thisArg, [argsArray])
调用一个具有给定this
值的函数,以及以一个数组(或类数组对象)的形式提供的参数。
call()
方法的作用和apply()
方法类似,区别就是call()
方法接受的是参数列表,而apply()
方法接受的是一个参数数组。
参数 | 描述 |
---|---|
thisArg | 可选的。在function 函数运行时使用的this 值。请注意,this 可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为null 或undefined 时会自动替换为指向全局对象,原始值会被包装。 |
argsArray | 可选的。一个数组或者类数组对象,其中的数组元素将作为单独的参数传给function 函数。如果该参数的值为null 或undefined ,则表示不需要传入任何参数。 |
// 把一个数组的全部元素添加到另一个数组中
var array = ['a', 'b'];
array.push.apply(array, [0, 1, 2]);
console.log(array); // ["a", "b", 0, 1, 2]
function sum() {
console.log("当前函数传了", arguments.length,"个参数");
var total = 0;
for (var i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
}
var total = sum.apply(null, [1,2,3,4,5,6,7,8,9]);
console.log(total); // 45
function sout(x, y) {
console.log(this.name, x, y);
}
var name = "全局name";
sout.apply(); // 全局name undefined undefined
sout.apply({name: "我是name"}); // 我是name undefined undefined
sout.apply({name: "我是name"}, ["666", 888]); // 我是name 666 888
sout.apply(null, ["666", 888]); // 全局name 666 888
function.bind(thisArg[, arg1[, arg2[, ...]]])
创建一个新的函数,在bind()
被调用时,这个新函数的this
被指定为 bind()
的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
参数 | 描述 |
---|---|
thisArg | 可选的。调用绑定函数时作为this 参数传递给目标函数的值。 如果使用new运算符构造绑定函数,则忽略该值。当使用bind 在setTimeout 中创建一个函数(作为回调提供)时,作为thisArg 传递的任何原始值都将转换为 object 。如果bind 函数的参数列表为空,或者thisArg 是null 或undefined ,执行作用域的this 将被视为新函数的thisArg 。 |
arg1, arg2, ... | 可选的。当目标函数被调用时,被预置入绑定函数的参数列表中的参数。 |
function sum() {
console.log("当前函数传了", arguments.length,"个参数");
var total = 0;
for (var i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
}
var bindSum = sum.bind(null, 1, 2, 3);
console.log(bindSum()); // 6
console.log(bindSum(6)); // 12
console.log(bindSum(6, 6)); // 18
function sout(x, y) {
console.log(this.name, x, y);
}
var name = "全局name";
sout.bind()(); // 全局name undefined undefined
sout.bind({name: "我是name"})(); // 我是name undefined undefined
sout.bind({name: "我是name"}, "666")("999"); // 我是name 666 999
sout.bind(null, "666", 888)("999"); // 全局name 666 888
封装js
对象
封装最简单的对象
将以下内容放在一个js文件中,引入js文件,使用AjaxUtil.xxx()
调用即可。
其实就是创建了一个js全局对象,里面的每个属性都是一个方法而已。
const AjaxUtil = {
/**
* ajax请求
* @param requestPath 请求路径
* @param requestData 请求参数,默认为空
* @param requestType 请求方式("POST" 或 "GET"), 默认为 "GET"
* @param callback 请求成功回调函数
*/
baseAjax: function (requestPath, requestData, requestType, callback) {
var load = layer.load();
$.ajax({
url: requestPath,
type: requestType || 'GET',
data: requestData || {},
success: function (res) {
layer.close(load);
if (callback) {
callback(res);
}
},
error: function () {
layer.close(load);
layer.alert("系统异常", {anim: 6, icon: 5, title: '提示'});
}
});
},
/**
* post请求 有参数
* @param path 请求路径
* @param data 请求参数
* @param callback 请求成功回调函数
*/
postByAjax: function (path, data, callback) {
this.baseAjax(path, data, 'POST', callback);
},
/**
* post请求 有参数 并且验证是否成功
* @param path 请求路径
* @param data 请求参数
* @param callback(data, res) 请求成功回调函数 data: 返回的数据 res: 返回的所有
*/
postByAjaxAndVerify: function (path, data, callback) {
this.postByAjax(path, data, function (res) {
if (res.code === 200) {
if (callback) {
callback(res.data, res);
}
} else {
layer.alert(res.msg, {anim: 6, icon: 5, title: '提示'});
}
});
},
/**
* post请求 无参数
* @param path 请求路径
* @param callback 请求成功回调函数
*/
noParamPostByAjax: function (path, callback) {
this.postByAjax(path, {}, callback);
},
/**
* get请求 有参数
* @param path 请求路径
* @param data 请求参数
* @param callback 请求成功回调函数
*/
getByAjax: function (path, data, callback) {
this.baseAjax(path, data, 'GET', callback);
}
};
但是这样写是存在一些问题的,我们无法定义一些只在工具类中使用方法,所有的方法属性,都是公开的,可以直接调用的。如果执行这些代码的作用域不是window
,那我们也不能在所有地方都可以调用的到。
怎么优雅的封装一个js
对象或插件?
这也是我一直在寻找的问题,怎么封装对象或插件是比较合理好用的呢?我也没有找到一个确切的方法。
既然找不到“参考答案”,那我们就来看看大佬们都是怎么做的,首先看看jQuery
,以下为jQuery
的部分源码,我么来分析一下。
分析jQuery
/*!
* jQuery JavaScript Library v3.6.0
* https://jquery.com/
*
* Includes Sizzle.js
* https://sizzlejs.com/
*
* Copyright OpenJS Foundation and other contributors
* Released under the MIT license
* https://jquery.org/license
*
* Date: 2021-03-02T17:08Z
*/
( function( global, factory ) {
"use strict";
if ( typeof module === "object" && typeof module.exports === "object" ) {
// For CommonJS and CommonJS-like environments where a proper `window`
// is present, execute the factory and get jQuery.
// For environments that do not have a `window` with a `document`
// (such as Node.js), expose a factory as module.exports.
// This accentuates the need for the creation of a real `window`.
// e.g. var jQuery = require("jquery")(window);
// See ticket #14549 for more info.
module.exports = global.document ?
factory( global, true ) :
function( w ) {
if ( !w.document ) {
throw new Error( "jQuery requires a window with a document" );
}
return factory( w );
};
} else {
factory( global );
}
// Pass this if window is not defined yet
} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
// enough that all such attempts are guarded in a try block.
"use strict";
...
var
version = "3.6.0",
// Define a local copy of jQuery
jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
// Need init if jQuery is called (just allow error to be thrown if not included)
return new jQuery.fn.init( selector, context );
};
...
var
// Map over jQuery in case of overwrite
_jQuery = window.jQuery,
// Map over the $ in case of overwrite
_$ = window.$;
jQuery.noConflict = function( deep ) {
if ( window.$ === jQuery ) {
window.$ = _$;
}
if ( deep && window.jQuery === jQuery ) {
window.jQuery = _jQuery;
}
return jQuery;
};
// Expose jQuery and $ identifiers, even in AMD
// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
// and CommonJS for browser emulators (#13566)
if ( typeof noGlobal === "undefined" ) {
window.jQuery = window.$ = jQuery;
}
return jQuery;
} );
大致就是定义了一个自调用函数,函数参数为当前作用域和一个初始化的函数,在自调用函数中调用了初始化的函数,初始化jQuery
方法,也就是$
方法,然后把该方法赋值给window
,使得我们在所有地方都可以使用。
分析layer
我们再看看layer
是怎么写的。
/*!
* layer - 通用 Web 弹出层组件
* MIT Licensed
*/
;!function(window, undefined){
"use strict";
...
//默认内置方法。
var layer = {
v: '3.5.1',
ie: function(){ //ie版本
var agent = navigator.userAgent.toLowerCase();
return (!!window.ActiveXObject || "ActiveXObject" in window) ? (
(agent.match(/msie\s(\d+)/) || [])[1] || '11' //由于ie11并没有msie的标识
) : false;
}(),
index: (window.layer && window.layer.v) ? 100000 : 0,
path: ready.getPath,
config: function(options, fn){
options = options || {};
layer.cache = ready.config = $.extend({}, ready.config, options);
layer.path = ready.config.path || layer.path;
typeof options.extend === 'string' && (options.extend = [options.extend]);
//如果设置了路径,则加载样式
if(ready.config.path) layer.ready();
if(!options.extend) return this;
isLayui
? layui.addcss('modules/layer/' + options.extend)
: ready.link('theme/' + options.extend);
return this;
},
//主体CSS等待事件
ready: function(callback){
var cssname = 'layer', ver = ''
,path = (isLayui ? 'modules/layer/' : 'theme/') + 'default/layer.css?v='+ layer.v + ver;
isLayui ? layui.addcss(path, callback, cssname) : ready.link(path, callback, cssname);
return this;
},
//各种快捷引用
alert: function(content, options, yes){
var type = typeof options === 'function';
if(type) yes = options;
return layer.open($.extend({
content: content,
yes: yes
}, type ? {} : options));
},
confirm: function(content, options, yes, cancel){
var type = typeof options === 'function';
if(type){
cancel = yes;
yes = options;
}
return layer.open($.extend({
content: content,
btn: ready.btn,
yes: yes,
btn2: cancel
}, type ? {} : options));
},
msg: function(content, options, end){ //最常用提示层
var type = typeof options === 'function', rskin = ready.config.skin;
var skin = (rskin ? rskin + ' ' + rskin + '-msg' : '')||'layui-layer-msg';
var anim = doms.anim.length - 1;
if(type) end = options;
return layer.open($.extend({
content: content,
time: 3000,
shade: false,
skin: skin,
title: false,
closeBtn: false,
btn: false,
resize: false,
end: end
}, (type && !ready.config.skin) ? {
skin: skin + ' layui-layer-hui',
anim: anim
} : function(){
options = options || {};
if(options.icon === -1 || options.icon === undefined && !ready.config.skin){
options.skin = skin + ' ' + (options.skin||'layui-layer-hui');
}
return options;
}()));
},
load: function(icon, options){
return layer.open($.extend({
type: 3,
icon: icon || 0,
resize: false,
shade: 0.01
}, options));
},
tips: function(content, follow, options){
return layer.open($.extend({
type: 4,
content: [content, follow],
closeBtn: false,
time: 3000,
shade: false,
resize: false,
fixed: false,
maxWidth: 260
}, options));
}
};
...
/** 内置成员 */
window.layer = layer;
...
}(window);
大致就是定义了一个自调用函数,函数参数为window
,在函数中初始化layer
对象,并把layer
对象赋值给window
,使得我们在所有地方都可以使用。
总结一下
- 都是定义一个自调用函数,不需要显示的调用,引入即执行。
- 在自调用函数中初始化要是用的对象或方法。
- 将初始化好的对象或方法赋值给
window
,让其全局可用。 - 放在一个
js文件
中,可对js内容进行压缩处理。 - 页面引入
js文件
直接使用。