数组的扩展
150讲轻松搞定Python网络爬虫
文章有点长,不废话,开干
扩展运算符
1.含义
...
(三个点代表拓展)
let arrayData = [`string`, `number`, `undefinded`, `boolean`, `null`, `object`];
// 使用拓展运算符,将数组完全展开
console.log(...arrayData);
使用场景(参数传递)-- 项目中常用(不只是下面实列)
1. // 定义箭头函数(ES6)
let fn_add = (a, b) => a + b;
const data = [12, 5];
// 控制台打印结果
console.info(fn_add(...data));
2. // 定义箭头函数
let push_data = (array, ...element) => {
array.push(...element);
// 打印结果
console.info(...array);
}
push_data([], [4, 5,`true`,`false`]);
结论:
上面代码中,array.push(...items)
和fn_add (...numbers)
这两行,都是函数的调用,它们的都使用了扩展运算符。该运算符将一个数组,变为参数序列。
3.与正常函数结合使用
function fn_test(v, w, x, y, z) {
console.log(v, w, x, y, z);
// 结果 -1 0 1 2 3
}
const argments = [0, 1];
fn_test(-1, ...argments, 2, ...[3]);
- 结合表达式使用
let x = 25;
// let x = -1;
const arr = [...(x > 0 ? ['a'] : []),'b'];
console.log(arr);
// 打印结果
['a','b'] 和 ['b']
- 如果扩展运算符后面是一个空数组,则不产生任何效果。
console.log([...[], 1]);
// 打印结果
// [1]
6.下面是扩展运算符取代apply
方法的一个实际的例子,应用Math.max方法,简化求出一个数组最大元素的写法。
// ES5 的写法
Math.max.apply(null, [34, 32, 22]);
// ES6 的写法
Math.max(... [34, 32, 22]);
// 等同于
Math.max(34, 32, 22);
7.日期中的使用
let dateTime = new Date(...[2020,7,6]);
console.log(dateTime.getFullYear() + `-`+ (dateTime.getMonth()) + `-` + dateTime.getDate());
// 结果 2020-7-6
2. 扩展运算符的应用
(1)复制数组
javascript中数组是一种复合数据类型,在内存中存储的是指针结构,如果复制数组,正常复制得到的数组并不是一个全新的数组。
const a = [1,2,3,4];
const b = a;
b[2] = 45;
console.log(a == b); // true
上述代码b并不是a的克隆,而是b指针和a指针指向同一份数据,所以修改b直接导致a的变化
在ES5复制一个全新数组需要调用方法来解决
const a = [31, 22];
const b = a1.concat();
b[0] = 2;
console.log(a == b); // false
在ES6中复制成一个全新的数组很容易
const data1 = [1, 2];
// 用法一
const data2 = [...data1 ];
// 用法二
//const [...data2] = data1 ;
console.log(data1 == data2); // false
(2)合并数组
const arrData1 = ['1', '2'];
const arrData2 = ['3'];
const arrData3 = ['4', '5'];
// ES5 中的合并数组
arrData1 .concat(arrData2 , arrData3 );
// [ '1', '2', '3', '4', '5' ]
// ES6 中的合并数组
[...arrData1 , ...arrData2 , ...arrData3 ]
// [ 'a', 'b', 'c', 'd', 'e' ]
(3)解构赋值
解构赋值的结合应用
1.获取数组中的第一项
ES6中的写法
let arrData = [`null`,`boolean`,`string`, `function`];
let [first, ...others] = arrData;
// 输出
console.log(first) // first
注意:扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错
const [first, ...middle, last] = [3, 2,90, 30, 42, 52]; // 报错
(4)字符串
字符串转换成真正的数组。
let str_char = `string-字符`;
// 输出 s t r i n g - 字 符
consle.log(...str_char);
总结:来测试一下(浏览器环境下)
let nodeList = document.querySelectorAll('div');
let array = [...nodeList];
// 输出什么?????
console.log(array);
3.ES6中数组实例的方法
(1)Array.from()
任何有length
属性的对象,都可以通过Array.from
方法转为数组(有例外)
Array.from
还可以接受第二个参数,作用类似于数组的map
方法,用来对每个元素进行处理,将处理后的值放入返回的数组。
1. Array.from() 将类数组对象转换成真正的数组。
// NodeList对象(浏览器环境中)
let arryDom = document.querySelectorAll(`section`);
// 输出
Array.form(arrayDom).map((elememt) => {
console.log(items);
});
// console.log(Array.from(arrayDom)); // 可忽略
2.第二个参数
let aData = '123';
Array.from(aData, (items)=>{
// 输出
console.log(items * 8);
});
(2)Array.of()
Array.of
方法用于将一组值,转换为数组。Array.of
总是返回参数值组成的数组。如果没有参数,就返回一个空数组。
Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1
(3)copyWithin
数组实例的copyWithin
方法,在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。也就是说,使用这个方法,会修改当前数组。
Array.prototype.copyWithin(target, start = 0, end = this.length)
它接受三个参数。
- target(必需):从该位置开始替换数据。如果为负值,表示倒数。
- start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示倒数。
- end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
- 这三个参数都应该是数值,如果不是,会自动转为数值。
let arrayCopty = [1, 2, 3, 4, 5].copyWithin(0, 3)
// 输出 [4, 5, 3, 4, 5]
console.log(arrayCopty);
上面代码表示将从 3 号位直到数组结束的成员(4 和 5),复制到从 0 号位开始的位置,结果覆盖了原来的 1 和 2。
(5)find() 和 findIndex()
1.数组实例的find
方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true
的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined
。
1.-find()
[1, 4, -5, 10].find((n) => n < 0)
// -5
上面代码找出数组中第一个小于 0 的成员。
[1, 5, 10, 15].find(function(value, index, arr) {
return value > 9
}) // 10
上面代码中,`find`方法的回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组。
2.-findIndex()
数组实例的`findIndex`方法的用法与`find`方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回`-1`。
[1, 5, 10, 15].findIndex(function(value, index, arr) {
return value > 9;
}) // 2
这两个方法都可以接受第二个参数,用来绑定回调函数的`this`对象。
function f(v){
return v > this.age;
}
let person = {name: 'John', age: 20};
[10, 12, 26, 15].find(f, person); // 26
上面的代码中,`find`函数接收了第二个参数`person`对象,回调函数中的`this`对象指向`person`对象。
(6)fill()
fill
方法使用给定值,填充一个数组。
['a', 'b', 'c'].fill(7)
// [7, 7, 7]
1.`fill`方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。
['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']
上面代码表示,`fill`方法从 1 号位开始,向原数组填充 7,到 2 号位之前结束。
注意,如果填充的类型为对象,那么被赋值的是同一个内存地址的对象,而不是深拷贝对象。
(7)数组实例的entries(),keys() 和 values()
可以用for...of
循环进行遍历,唯一的区别是keys()
是对键名的遍历、values()
是对键值的遍历,entries()
是对键值对的遍历。
for (let index of ['c', 'd'].keys()) {
// 输出
console.log(index);
// 0
// 1
}
for (let elem of ['a', 'b'].values()) {
console.log(elem);
}
// 输出
// 'a'
// 'b'
3. 同时获取key和value
for (let [index, elem] of ['a', 'b'].entries()) {
console.log(index, elem);
}
// 输出
// 0 "a"
// 1 "b"
4.如果不使用`for...of`循环,可以手动调用遍历器对象的`next`方法,进行遍历。
let letter = ['a', 'b', 'c'];
let entries = letter.entries();
console.log(entries.next().value); // [0, 'a']
console.log(entries.next().value); // [1, 'b']
console.log(entries.next().value); // [2, 'c']
(8)includes()
Array.prototype.includes
方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes
方法类似。ES2016 引入了该方法。
该方法的第二个参数表示搜索的起始位置,默认为0
。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为-4
,但数组长度为3
),则会重置为从0
开始。
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
下面代码用来检查当前环境是否支持该方法,如果不支持,部署一个简易的替代版本。
const contains = (() =>
Array.prototype.includes
? (arr, value) => arr.includes(value)
: (arr, value) => arr.some(el => el === value)
)();
contains(['foo', 'bar'], 'baz'); // => false
(9)数组中的空位
数组的空位指,数组的某一个位置没有任何值。比如,Array
构造函数返回的数组都是空位。注意,空位不是undefined
,一个位置的值等于undefined
,依然是有值的。空位是没有任何值,in
运算符可以说明这一点。
0 in [undefined, undefined, undefined] // true
0 in [, , ,] // false
ES6 则是明确将空位转为undefined
。Array.from
方法会将数组的空位,转为undefined
,也就是说,这个方法不会忽略空位。
Array.from(['a',,'b'])
// [ "a", undefined, "b" ]
扩展运算符(...
)也会将空位转为undefined
。
[...['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
上面代码中,数组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
由于空位的处理规则非常不统一,所以建议避免出现空位。
ES5 对空位的处理,已经很不一致了,大多数情况下会忽略空位。
forEach()
,filter()
,reduce()
,every()
和some()
都会跳过空位。map()
会跳过空位,但会保留这个值join()
和toString()
会将空位视为undefined
,而undefined
和null
会被处理成空字符串。
// forEach方法
[,'a'].forEach((x,i) => console.log(i)); // 1
// filter方法
['a',,'b'].filter(x => true) // ['a','b']
// every方法
[,'a'].every(x => x==='a') // true
// reduce方法
[1,,2].reduce((x,y) => return x+y) // 3
// some方法
[,'a'].some(x => x !== 'a') // false
// map方法
[,'a'].map(x => 1) // [,1]
// join方法
[,'a',undefined,null].join('#') // "#a##"
// toString方法
[,'a',undefined,null].toString() // ",a,,"
Google开发专家带你学 AI:入门到实战(Keras/Tensorflow)(附源码)