数组扩展
数组扩展运算符
数组扩展运算符(spread)是三个点(...)。它好比rest参数的逆运算,将一个数组转为用空格分隔的参数序列。
console.log(...[1, 2, 3]); // 1 2 3console.log(1, ...[2, 3, 4], 5); // 1 2 3 4 5
⚠️rest参数是运用在函数参数上的,将函数参数转换为数组的形式,如下:
function fn(...values) { console.log(values); // ['jia', 'ming']}fn('jia', 'ming');
下面我们结合数组扩展运算符和rest参数来实现一个类似call的方法call2操作:
Function.prototype.call2 = function(context, ...args){ // 这里使用到rest参数context = context || window; // 因为传递过来的context有可能是nullcontext.fn = this; // 让fn的上下文为contextconst result = context.fn(...args); // 这里使用了数组扩展运算符delete context.fn;return result; // 因为有可能this函数会有返回值return}var job = 'outter teacher';var obj = {job: 'inner teacher'};function showJob() {console.log(this.job);}showJob(); // outter teachershowJob.call2(obj); // inner teacher
复习一下,我们把var job = 'outter teacher'改为let job = 'outter teacher'后,showJob()会输出什么?
答案是undefined。在前一篇中也提到过,ES6语法声明的变量是不会挂载在全局对象上的~
Array.from()
Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(对象包括ES6新增的数据结构Set和Map)。
// 类数组转化成数组let arrayLike = {'0': 'a','1': 'b','2': 'c',length: 3}// ES5的写法var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']// ES6的写法let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
Array.of()
Array.of()方法用于将一组值,转换为数组。
let arr = Array.of(2, 3, 'reng');console.log(arr); // [2, 3, 'reng']console.log(arr.pop()); // reng
Array.of基本上可以弥补Array()或new Array()带来的因为参数个数导致的不同行为。Array.of基本上可以替代它们两个了。
Array.of(); // []Array.of('reng'); // ['reng']Array.of(2, 'reng'); // [2, 'reng']
数组中还有其它有用的方法:
- copyWithin(target, start = 0, end = this.length): 拷贝指定数组的范围值
- find(fn): 用于查找第一个符合条件的数组成员,没有返回undefined
- findIndex(fn): 用于查找第一个符合条件的数组成员的位置,没有返回-1
- entries(): 对键值对的遍历
- keys(): 对键的遍历
- values(): 对值的遍历
- includes(el): 返回一个布尔值,表示某个数组是否包含给定的值,与字符串的include(el)方法相似
- flat(num): 将嵌套的数组拉平,num是遍历的深度
[1, [2, [3]]].flat(Infinity);// [1, 2, 3]
有这么一个需求:将数组[[2, 8], [2], [[4, 6], 7, 6]]转成一维且元素不重复的数组。
我们的实现方案如下:
let arr = [[2, 8], [2], [[4, 6], 7, 6]];console.log([...new Set(arr.flat(Infinity))]); // [2, 8, 4, 6, 7]
对象扩展
属性名表达式
ES6允许字面量定义对象时,把表达式放在方括号内:
let lastWord = 'last word';const a = { 'first word': 'hello', [lastWord]: 'world', ['end'+'symbol']: '!' };a['first word'] // 'hello'a[lastWord] // 'world'a['last word'] // 'world'a['endsymbol'] // '!'
对象的扩展运算符
上面整理数组扩展内容的时候,提到了数组的扩展运算符。ES2018将这个运算符引入了对象~
let z = { a: 3, b: 4 };let n = { ...z }; // 关键点n // { a: 3, b: 4 }
对象中某些新增的方法
- Object.is(arg1, arg2): 比较两个值是否严格相等,与===行为基本一致
- Object.assign(target, source1, ...): 用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。属于浅拷贝
- Object.keys(obj): 返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名
- Object.values(obj): 方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
- Object.entries(obj): 方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。
const obj = { foo: 'bar', baz: 42 };Object.entries(obj)// [ ["foo