目录 :
(十四)数组的扩展
(十五)对象的扩展
(十四)数组的扩展
这里我整理了 ES5 与 ES6 中关于数组的扩展
ES5
array.forEach(callback[,thisObject ])
数组循环
第一个参数是一个回调函数,并且这个回调函数有默认的参数,分别是 value、index、array自身
let arr = [1,2,4];
arr.forEach(console.log);
// 1 0 Array [ 1, 2, 4 ]
// 2 1 Array [ 1, 2, 4 ]
// 4 2 Array [ 1, 2, 4 ]
arr.forEach(function(value,index){
console.log("只输出两个属性"+value,index);
});
// 只输出两个属性 1 0
// 只输出两个属性 2 1
// 只输出两个属性 4 2
第二个参数是上下文参数,就是回调函数中的this指向,默认是window对象,严格模式下是 undefined
let group = {
member: ['a1', 'a2', 'b1', 'b2', 'c1', 'c2'],
isActive: function(member){
return /1$/.test(member);
},
active: function(member){
if(this.isActive(member)){
console.log(member + '是活跃成员');
}
}
}
// 将回调函数的this设置为group
group.member.forEach(group.active, group);
// a1是活跃成员
// b1是活跃成员
// c1是活跃成员
array.map(callback[, thisObject])
映射方法, 必须要用return返回值, 返回的值就是新数组中映射的值
第一个参数是一个回调函数,并且这个回调函数有默认的参数,分别是 value、index、array自身
第二个参数是上下文参数,就是回调函数中的this指向,默认是window对象,严格模式下是 undefined
let arr = [1, 2, 3, 4, 5];
let mapArr = arr.map(function(value){
return value*value;
});
console.log(mapArr); //[1, 4, 9, 16, 25]
array.filter(callback[, thisObject])
过滤掉“不合格”的元素如果在回调函数中返回true,那么就留下来,返回false,就扔掉
第一个参数是一个回调函数,并且这个回调函数有默认的参数,分别是 value、index、array自身
第二个参数是上下文参数,就是回调函数中的this指向,默认是window对象,严格模式下是 undefined
let arr = [5, 20, 24, 66, 40, 49, 60];
let newArr = arr.filter(function(value){
return value % 10 == 0;
});
console.log(newArr); //[20, 40, 60]
array.some(callback[, thisObject])
只要有一个满足条件就返回true,否则返回false
第一个参数是一个回调函数,并且这个回调函数有默认的参数,分别是 value、index、array自身
第二个参数是上下文参数,就是回调函数中的this指向,默认是window对象,严格模式下是 undefined
let arr = [1,50,3,20,8,9,33];
let flag = arr.some(function (value) {
return value % 3 == 0;
});
console.log(flag); // true,表明 arr 数组中至少存在一个能被3整除的
array.every(callback[, thisObject])
只要有一个不满足条件就返回false,否则返回true
第一个参数是一个回调函数,并且这个回调函数有默认的参数,分别是 value、index、array自身
第二个参数是上下文参数,就是回调函数中的this指向,默认是window对象,严格模式下是 undefined
let arr = [1,50,3,20,8,9,33];
let flag = arr.every(function (value) {
return value % 3 == 0;
});
console.log(flag); // false 表明 arr 数组中不符合所有都能被3整除
array.indexOf(searchElement[, fromIndex])
第一个参数表示要查找的元素,第二个参数可选,表示从第几位开始查找
let arr = [10, 20, 30, 40,30, 60];
let index = arr.indexOf(30);
let index2 = arr.indexOf(30,3);
console.log(index); //2
console.log(index2); //4
array.lastIndexOf(searchElement[, fromIndex])
从后往前进行查找
let arr = [10, 20, 30, 40,30, 60];
let index = arr.lastIndexOf(30);
let index2 = arr.lastIndexOf(30,3);
console.log(index); //4
console.log(index2); //2
array.reduce(callback[, initialValue])
“浓缩”
不断的减少数组元素,最终的到一个结果
第一个参数同样是一个回调函数,参数分别是 previous、current、index、array(之前值、当前值、数组索引、数组引用);
let arr = [1, 2, 3,4];
let result = arr.reduce(function(pre,cur){
return pre*cur;
});
// 类似于累乘
console.log(result); // 24
第二个参数可选,表示初始值
let arr = [1, 2, 3,4];
let result = arr.reduce(function(pre,cur){
return pre+cur;
},10);
// 加号是累加,第二个参数,相当与向数组添加一个元素
console.log(result); // 20
array.reduceRight(callback[, initialValue])
从右向左“浓缩”
第一个参数同样是一个回调函数,参数分别是 previous、current、index、array(之前值、当前值、数组索引、数组引用);
let arr = [2, 4, 3];
let result = arr.reduceRight(function(pre, cur){
return Math.pow(pre, cur);
});
console.log(result); // 3^4^2 = 6561
第二个参数可选,表示初始值
let arr = [2, 4, 3];
let result = arr.reduceRight(function(pre, cur){
return Math.pow(pre, cur);
},2);
console.log(result); // 2^3^4^2 = 16777216
ES6
Array.from()
将类似数组的对象 和 可遍历(部署了Iterator接口)的对象 转为真正的数组
第一个参数是要转换为数组的对象
注意: 任何有length属性的对象,都可以通过Array.from方法转为数组
实际应用中,常见的类似数组的对象是DOM操作返回的NodeList集合,以及函数内部的arguments对象。
// NodeList对象
let ps = document.querySelectorAll('p');
Array.from(ps).forEach(function (p) {
console.log(p);
});
// arguments对象
function foo() {
var args = Array.from(arguments);
// ...
}
只要是部署了Iterator接口的数据结构,Array.from都能将其转为数组。
Array.from('hello')
// ['h', 'e', 'l', 'l', 'o']
let namesSet = new Set(['a', 'b'])
Array.from(namesSet) // ['a', 'b']
Array.from还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组。
let arrayLike = {
'0':2,
'1': 3,
'2': 1,
length: 3
};
console.log(Array.from(arrayLike, (x) => x * x)); // 4,9,1
// // 等同于
// Array.from(arrayLike).map(x => x * x);
Array.of()
将一组值,转换为数组,总是返回参数值组成的数组。如果没有参数,就返回一个空数组。
Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1
copyWithin(target,start,end)
三个参数
target(必需):从该位置开始替换数据。
start(可选):从该位置开始读取数据,默认为0。如果为负值,表示倒数。
end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
// 将3号位复制到0号位
[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
// [4, 2, 3, 4, 5]
// -2相当于3号位,-1相当于4号位
[1, 2, 3, 4, 5].copyWithin(0, -2, -1)
// [4, 2, 3, 4, 5]
find()和findIndex()
find() 用于找出第一个符合条件的数组成员,然后返回该成员,如果没有则返回 undefined
findIndex 返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。
回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组
这两个方法都可以接受第二个参数,用来绑定回调函数的this对象。
let arr = [0,-3,4,7,92,88];
let flag = arr.find(function (value) {
return value < 0;
} );
console.log(flag);
fill()
使用给定值,填充一个数组
fill方法用于空数组的初始化非常方便。数组中已有的元素,会被全部抹去。
还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。
['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']
entries()
对键值对的遍历
keys()
对键名的遍历
values()
对键值的遍历
let arr = [0,-3,4];
for(let index of arr.entries()){
console.log(index);
}
// 0,0
// 1,-3
// 2,4
for(let val of arr.values()){
console.log(val);
// arr.values is not a function
}
for(let key of arr.keys()){
console.log(key);
}
// 0
// -3
// 4
includes()
返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes方法类似
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
[1, 2, NaN].includes(NaN); // true
该方法的第二个参数表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为-4,但数组长度为3),则会重置为从0开始。
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
Map、Set 的has()与includes()区分
Map.prototype.has(key) :查找键名
Set.prototype.has(value):查找键值
数组的空位
指数组的某一个位置没有任何值,空位不是undefined,一个位置的值等于undefined,依然是有值的。空位是没有任何值
Array.from转化数组时,会把空位转为undefined
console.log(Array.from([4, , -2])); //Array [ 4, undefined, -2 ]
扩展运算符(…)也会将空位转为undefined
console.log([...['a',,'b']]); // [ "a", undefined, "b" ]
copyWithin()会连空位一起拷贝
[,'a','b',,].copyWithin(2,0) // [,"a",,"a"]
fill()会将空位视为正常的数组位置
new Array(3).fill('a') // ["a","a","a"]
for…of循环也会遍历空位
let arr = [, ,];
for (let i of arr) {
console.log(1);
}
// 1
// 1
(十五)对象的扩展
属性的简洁表示法
// 变量
var baz = {foo};
// 等同于
var baz = {foo: foo};
//方法
let obj = {
name,
show:function () {
return "show me ";
}
}
// 等同于
let obj2 = {
name,
show(){
return "show2 me";
}
}
console.log(obj.show()); // show me
console.log(obj2.show()); // show2 me
属性名表达式
第一种是直接用标识符作为属性名
第二种是用表达式作为属性名,这时要将表达式放在方括号之内
// 直接用标识符
obj.foo = true;
// 使用表达式
obj['a' + 'bc'] = 123;
注意,属性名表达式与简洁表示法,不能同时使用,会报错。
// 报错
var foo = 'bar';
var bar = 'abc';
var baz = { [foo] };
// 正确
var foo = 'bar';
var baz = { [foo]: 'abc'};
Object.is()
用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。
Object.is('foo', 'foo')
// true
Object.is({}, {})
// false
不同之处只有两个:一是+0不等于-0,二是NaN等于自身。
+0 === -0 //true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
Object.assign()
用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)
第一个参数是目标对象,后面的参数都是源对象
如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
let target = { a: 1 };
let source1 = { b: 2 };
let source2 = { c: 3 };
let source3 = { a: 3 };
console.log(Object.assign({target}, source1, source2,source3)); // {a:3, b:2, c:3}
如果只有一个参数,Object.assign会直接返回该参数。
var obj = {a: 1};
Object.assign(obj) === obj // true
如果该参数不是对象,则会先转成对象,然后返回。
typeof Object.assign(2) // "object"
由于undefined和null无法转成对象,所以如果它们作为参数,就会报错
Object.assign(undefined) // 报错
Object.assign(null) // 报错
注意
Object.assign方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用
遍历对象
(1)Object.keys()
返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名
let obj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(obj)); //[ "2", "7", "100" ]
(2)Object.values()
返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值
let obj = { foo: 'bar', baz: 42 };
console.log(Object.values(obj)); // ["bar", 42]
属性名为数值的属性,是按照数值大小,从小到大遍历的,因此返回的顺序是b、c、a
let obj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.values(obj)); // ["b", "c", "a"]
如果参数是一个字符串,会返回各个字符组成的一个数组
console.log(Object.values("hello")); //[ "h", "e", "l", "l", "o" ]
如果参数是数值或布尔值,由于数值和布尔值的包装对象,都不会为实例添加非继承的属性。所以,Object.values会返回空数组。
Object.values(42) // []
Object.values(true) // []
(3)Object.entries()
返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组
Object.entries的基本用途是遍历对象的属性。
Object.entries方法的另一个用处是,将对象转为真正的Map结构。
var obj = { foo: 'bar', baz: 42 };
var map = new Map(Object.entries(obj));
map // Map { foo: "bar", baz: 42 }
对象的扩展运算符
(1)解构赋值
从一个对象取值,相当于将所有可遍历的、但尚未被读取的属性,分配到指定的对象上面。所有的键和它们的值,都会拷贝到新对象上面
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 }
解构赋值的拷贝是浅拷贝,即如果一个键的值是复合类型的值(数组、对象、函数)、那么解构赋值拷贝的是这个值的引用,而不是这个值的副本
let obj = { a: { b: 1 } };
let { ...x } = obj;
obj.a.b = 5;
console.log(x.a.b );// 5
另外,解构赋值不会拷贝继承自原型对象的属性
下面代码中,对象o3是o2的拷贝,但是只复制了o2自身的属性,没有复制它的原型对象o1的属性
let o1 = { a: 1 };
let o2 = { b: 2 };
o2.__proto__ = o1;
let o3 = { ...o2 };
o3 // { b: 2 }
(2)扩展运算符
扩展运算符(…)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中
有同名属性,后面的属性值会覆盖前面的属性值
let z = { a: 3, b: 4 };
let n = {a:2, ...z };
console.log(n); // { a: 3, b: 4 }