1. 扩展运算符
扩展运算符(spread)是三个点(...
)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
console.log(...[1, 2, 3])
// 1 2 3
console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
[...document.querySelectorAll('div')]
// [, , ]
该运算符将一个数组,变为参数序列。
1.1 扩展运算符后可以为表达式
const arr = [
...(x > 0 ? ['a'] : []),
'b',
];
如果扩展运算符后面是一个空数组,则不产生任何效果。
[...[], 1]
// [1]
1.2 替代了apply方法
// ES5 的写法
function f(x, y, z) {
// ...
}
var args = [0, 1, 2];
f.apply(null, args);
// ES6的写法
function f(x, y, z) {
// ...
}
let args = [0, 1, 2];
f(...args);
1.3 可以快速取出数组中的最大值
//es5
Math.max.apply(null,[1,5,2,8]) // 8
//es6
Math.max(...[1,5,2,8])//8
//上面两种方法等同于
Math.max(1,5,2,8)
1.4 复制数组
//es5
const a1 = [1, 2];
const a2 = a1.concat();
a2[0] = 2;
a1 // [1, 2]
扩展运算符提供了复制数组的简便写法。
const a1 = [1, 2];
// 写法一
const a2 = [...a1];
// 写法二
const [...a2] = a1;
1.5 合并数组
扩展运算符提供了数组合并的新写法。
// ES5
[1, 2].concat(more)
// ES6
[1, 2, ...more]
var arr1 = ['a', 'b'];
var arr2 = ['c'];
var arr3 = ['d', 'e'];
// ES5的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]
// ES6的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]
1.6. 与解构组合使用
扩展运算符可以与解构赋值结合起来,用于生成数组。
// ES5
a = list[0], rest = list.slice(1)
// ES6
[a, ...rest] = list
下面是另外一些例子。
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]
const [first, ...rest] = [];
first // undefined
rest // []
const [first, ...rest] = ["foo"];
first // "foo"
rest // []
const [...butLast, last] = [1, 2, 3, 4, 5];
// 报错
const [first, ...middle, last] = [1, 2, 3, 4, 5];
// 报错
1.7. 类数组转数组
扩展运算符还可以将字符串转为真正的数组。
[...'hello']
// [ "h", "e", "l", "l", "o" ]
let nodeList = document.querySelectorAll('div');
let array = [...nodeList];
2. 数组循环
2.1 . 常用循环
for(var i = 0; i < arr.length; i++){
}
while(){
}
2.2. ES 5 新增的循环方法
新增的循环都是数组身上的方法
- arr.forEach()
- arr.map()
- arr.filter()
- arr.some()
- arr.every()
以上这些方法接收的参数一模一样,接受两个参数
第一个: 就是循环的回调函数
第二个: 你希望this指向谁,这个参数用的少
2.2.1 forEach用法
在看看forEach的用法
// arr.forEach()
// forEach其实就是for循环,for里面循环变量的,自增啊,forEach就简单多了
var arr = ["a","b","c","d"]
arr.forEach(function(value,index,arr){
console.log(value,index,arr);
})
// forEach 就是用来代替我们for循环的
forEach的this
var arr = ["a","b","c","d"]
arr.forEach(function(value,index,arr){
console.log(this); // 此时this是window
console.log(value,index,arr);
})
// 如果传了第二个参数
var arr = ["a","b","c","d"]
arr.forEach(function(value,index,arr){
console.log(this); // 此时this就是#document
console.log(value,index,arr);
},document)
如果使用箭头函数,那么this就会发生变化
var arr = ["a","b","c","d"]
arr.forEach((value,index,arr) => {
console.log(this); // 此时this就是window
console.log(value,index,arr);
})
// 添加第二个参数
var arr = ["a","b","c","d"]
arr.forEach((value,index,arr) => {
console.log(this); // 此时this还是window
console.log(value,index,arr);
},document)
// 箭头函数里面的this指向函数定义时的this
// 将代码放到一个对象中
var obj= {
name: function(){
var arr = ["a","b","c","d"]
arr.forEach((value,index,arr) => {
console.log(this); // 此时this还是obj
console.log(value,index,arr);
},document)
}
}
// 此时obj.name() this指向obj
2.2.2 map
翻译过来就是地图(映射),非常有用,尤其是数据交互
正常情况下,需要配合return使用,返回新数组,如果没有return,这个就相当于forEach
forEach 返回undefined
map如果没有return 则返回元素项数个undefined组成的新数组
// arr.map()
let arr= [
{title: "aa",read: 100},
{title: "aa",read: 100},
{title: "aa",read: 100}
]
let newArr = arr.map((item,index,arr) => {
console.log(item,index,arr);
return item;
})
注意
平时只用用map,就一定要有return,否则你就用forEach 不要走我map了
map 可以重新整理我们的数据结构
// arr.map() 整理后台传过来的数据
let arr= [
{title: "aa",read: 100},
{title: "bb",read: 20},
{title: "cc",read: 50}
]
let newArr = arr.map((item,index,arr) => {
let json = {};
json.shop = `*${item.title}--`;
json.price = `¥${item.read}元`
return json;
})
console.log(arr);
console.log(newArr);
2.2.3 filte
过滤,过滤一些不合格的元素,如果回调函数返回true,就留下来,添加到返回的新数组中,为false就过滤
// arr.filter() 过滤
let arr= [
{title: "aa",read: 100},
{title: "bb",read: 20},
{title: "cc",read: 50}
]
let newArr = arr.filter((item,index,arr) => {
return item.read > 50;
})
console.log(arr);
console.log(newArr);
filte方法去重
let arr = [2,1,3,5,2,3,1];
let newArr = arr.filter((val,index,arr)=>{
return arr.indexOf(val) == index;
})
console.log(newArr); // [2, 1, 3, 5]
2.2.4 some every
这个方法感觉像查找比对的意思,返回的结果是布尔值
let arr = ["a","b","c","d"]
let b = arr.some((item,index,arr) => {
return item == "c";
})
console.log(b); // true
只要在回调中返回一个true 那么整个结果就是true,
感觉像查询,数组中只要有一项符合条件,那么就返回true,如果都是false 那结果就是false
// every 判断数组里面是不是都是奇数
let arr = [1,3,7,9,5]
let b = arr.every((item,index,arr) => {
return item % 2 == 1;
})
console.log(b); // true
而every则刚好相反,every是数组中每一项都为true,才返回true ,只要有一项不符合条件都是false
来封装一个小功能
let arr = ["apple","banana","orange"]
function finedInArray(arr,item){
return arr.some((val,index,arr) => {
return val == item;
})
}
console.log(finedInArray(arr,"orange")); // true
接下来reduce和reduceRight接收的参数和上面方法都不一样了
2.2.5 reduce reduceRight
reduce
从左往右计算
reduceRight
是从右往左计算
用的极少,比如求数组的和,阶乘都可以
let arr = [1,2,3,4,5,6,7,8,9,10]
let res = arr.reduce((prev,cur,index,arr) => {
// console.log(arguments);
return prev + cur;
})
console.log(res); //55
prev是上一次的运算结果,cur是当前的值,index是当前的下标,arr是当前的数组
数组去重
let arr = [1,2,2,4,5,4,7,5,6,1]
let res = arr.reduce(function(prev,cur,index,arr){
//console.log(arguments);
if(!prev.includes(cur)){
prev.push(cur)
}
return prev;
},[])
console.log(res);
3.ES 6 新增的循环
es6引入的作为遍历所有数据结构的统一的方法。
一个数据结构只要部署了Symbol.iterator
属性,就被视为具有 iterator 接口,就可以用for...of
循环遍历它的成员。也就是说,for...of
循环内部调用的是数据结构的Symbol.iterator
方法。
3.1. for ... of 循环
arr.keys() 数组下标集合
arr.values() 数组值集合
arr.entries() 数组的每一项的集合
entries()
,keys()
和values()
——用于遍历数组。它们都返回一个遍历器对象,可以用for...of
循环进行遍历,唯一的区别是keys()
是对键名的遍历、values()
是对键值的遍历,entries()
是对键值对的遍历。
let arr = ["apple","banana","orange"];
for(let val of arr){
console.log(val);
}
// 和for循环很像
// 这个只是循环值,如果循环索引怎么办
for(let index of arr.keys()){
console.log(index);
}
// arr.keys() 就是arr数组索引的集合
// 如果想索引和值一起循环
for(let item of arr.entries()){
console.log(item); // item 是有数组的下标和值组成的数组如[0,"apple"]
}
// 也可以像下面这样写
for(let [key, val] of arr.entries()){
console.log(key, val); // 打印索引和值 0 "apple"
}
4.ES6 数组新增方法
4.1. Array.from()
作用: 把类数组(获取一组元素,arguments)对象转成数组
4.1.1 拷贝数组
// ES5的方法
var arr2 = [].slice.call(arr);
var arr2 = Array.prototype.slice.call(arr);
// ES6的方法
let arr = [1,2,3];
let arr2 = [...arr];
// 第二种就是
let arr3 = Array.from(arr);
4.1.2 Array.from()
参数:
- 第一个参数:一个类数组对象,用于转为真正的数组
- 第二个参数:类似于数组的
map
方法,用来对每个元素进行处理,将处理后的值放入返回的数组。
- 第三个参数:如果
map
函数里面用到了this
关键字,还可以传入Array.from
的第三个参数,用来绑定this
。
// 将arguments转数组
function haha(){
console.log(arguments); // 类数组
console.log(Array.from(arguments)); // 数组
}
haha(1,2,3,4)
什么是类数组.有length就靠谱
var str = "wuwei";
var arr = Array.from(str);
console.log(arr); // 此时arr就是一个数组了
var obj = {
0: "a",
1: "b",
2: "c",
length: 3
}
var arr = Array.from(obj); // ["a", "b", "c"]
4.2. Array.of()
把一组值转成数组
var arr = Array.of("a","b","c","d");
这个方法的主要目的,是弥补数组构造函数Array()
的不足。因为参数个数的不同,会导致Array()
的行为有差异。
//Array
Array() // []
Array(3) // [, , ,]
Array(3, 11, 8) // [3, 11, 8]
Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1
4.3. arr.find()
查找第一个符合要求的数组成员,返回值,如果没找到,则返回undefined
var arr = [50,10,201,103,62,81];
var res = arr.find((val , index ,arr) => {
// console.log(arguments)
return val > 100;
})
console.log(res); // 201
4.4. arr.findIndex()
和find()很像,这是这里找的是位置,返回条件为真时的索引;没找到返回-1
var arr = [50,10,201,103,62,81];
var res = arr.findIndex((val , index ,arr) => {
return val > 100;
})
console.log(res); // 2
4.5.arr.fill()
arr.fill(需要填充的值, 填充开始位置,填充结束位置);
填充内容不包括结束的位置
var arr = new Array(3);
arr.fill("默认值");
console.log(arr); //["默认值", "默认值", "默认值"]
// 完整用法
var arr = new Array(10);
arr.fill("默认值",1,3);
console.log(arr); // [empty, "默认值", "默认值", empty × 7]
5. ES2016里面新增
5.1. arr.includes()
查看数组中是否包含参数的值,返回布尔值
var arr = ["apple" , "origan","banana"];
var a = arr.includes("apple");
console.log(a); // true
var b = arr.includes("apple2");
console.log(b); // false
以前我们判断是使用indexOf 判断,结果为-1就是不包含
没有该方法之前,我们通常使用数组的indexOf
方法,检查是否包含某个值。
indexOf
方法有两个缺点,一是不够语义化,它的含义是找到参数值的第一个出现位置,所以要去比较是否不等于-1
,表达起来不够直观。二是,它内部使用严格相等运算符(===
)进行判断,这会导致对NaN
的误判。
6.关于数组的空位
数组的空位指,数组的某一个位置没有任何值。
注意,空位不是undefined
,一个位置的值等于undefined
,依然是有值的。空位是没有任何值,in
运算符可以说明这一点。
0 in [undefined, undefined, undefined] // true
0 in [, , ,] // false
ES5 对空位的处理,已经很不一致了,大多数情况下会忽略空位。
-
forEach()
, filter()
, reduce()
, every()
和some()
都会跳过空位。
-
map()
会跳过空位,但会保留这个值
-
join()
和toString()
会将空位视为undefined
,而undefined
和null
会被处理成空字符串。
ES6 则是明确将空位转为undefined
。
Array.from
方法会将数组的空位,转为undefined
,也就是说,这个方法不会忽略空位。
Array.from(['a',,'b'])
// [ "a", undefined, "b" ]
扩展运算符(...
)也会将空位转为undefined
。
[...['a',,'b']]
// [ "a", undefined, "b" ]
fill()
会将空位视为正常的数组位置。
new Array(3).fill('a') // ["a","a","a"]
for...of
循环也会遍历空位。
let arr = [, ,];
for (let i of arr) {
console.log(1);
}
// 1
// 1
上面代码中,数组arr
有两个空位,for...of
并没有忽略它们。如果改成map
方法遍历,空位是会跳过的。
entries()
、keys()
、values()
、find()
和findIndex()
会将空位处理成undefined
。
// entries()
[...[,'a'].entries()] // [[0,undefined], [1,"a"]]
// keys()
[...[,'a'].keys()] // [0,1]
// values()
[...[,'a'].values()] // [undefined,"a"]
// find()
[,'a'].find(x => true) // undefined
// findIndex()
[,'a'].findIndex(x => true) // 0
由于空位的处理规则非常不统一,所以建议避免出现空位。