ES6+ 新特性

您所在的位置:网站首页 es6新特性是什么 ES6+ 新特性

ES6+ 新特性

2023-11-06 20:53| 来源: 网络整理| 查看: 265

一、写在前面

笔者是一名本科大二前端小白,在此留下前端学习过程中值得记录的一切。 在这个系列中,笔者整理了在学习ES6+过程中遇到的实用新特性。 内容参考了W3C、菜鸟等文档教程,也有笔者对初次学习该知识点时笔记的总结。

本期带大家了解解构赋值的内容,并熟悉它的语法和使用场景。 由于是笔者的第一篇文章,如果有瑕疵、错误,欢迎大家在评论区指出、交流!

二、解构赋值是什么?

是对赋值运算符的扩展,对数组/对象进行模式匹配,然后对其中的变量进行赋值。 就是一种打破数据结构,将其拆分为更小部分的过程。 如此就能让代码更加简洁易读,语义更加清晰明了。

三、为什么需要它?

假设我们有一个数据对象,其中还内嵌了两级对象以存储更加具有层次的数据:

const trainee = { name: 'cxk', age: 24, skills: { sing: { song: 'jntm' } jump: 99, rap: 98 } } function showSkill(trainee){ console.log('名:' + trainee.name); console.log('唱:' + trainee.skills.sing.song); console.log('rap:' + trainee.skills.rap); }

某些属性由于还具有多级子对象,访问的深度加大,这意味着在写代码时需要更多的输入。

但是通过解构赋值,我们可以用更简洁的语法、更有表现力的写法来实现一样的效果。

四、语法 1. 数组

ES5中为变量赋值,只能直接一个个地指定值。

let c = 1, x = 2, k = 3;

解构赋值却允许这样写:

let [c, x, k] = [1, 2, 3]; // 可以从数组中提取值,按照对应位置,对变量赋值。

这种写法属于模式匹配,只要等号两边的模式相同,左边变量就会被赋予右边对应的值。

如果等号右边不是可遍历的结构(包括数、布尔值、null、undefined),那就会报错。

let [a] = 0; let [a] = true; let [a] = undefined; let [a] = {}; // 都报错!

为什么这些数据类型不能被遍历呢?其实在解构时默认会去调用Iterator接口,如果该数据类型没有Iterator接口,就不可被遍历!

在这里笔者有必要介绍一下Iterator接口:

是一种迭代器,为各种不同的数据结构提供统一的访问机制,主要表现为遍历操作。 任何数据类型只要部署了Iterator接口,就可以被遍历(迭代)。 在ES6中只要一个数据类型具有Symbol.iterator属性,那么就认为是可迭代的。 包括Array、Map、Set、arguments、String。 字符串可以解构赋值是因为此时被转换成了一个类似数组的对象。

以下代码简单实现Iterator接口:

let cxk = [1, 2, 3]; // 依次处理数据类型里的每个成员 function Iterator(cxk) { let index = 0; return { next: () => { if (index < cxk.length) { return { value: cxk[index++], isDone: false } } else { return { value: undefined, isDone: true } } } } } let trainee = cxk[Symbol.iterator](); console.log(trainee.next()); console.log(trainee.next()); console.log(trainee.next()); console.log(trainee.next());

打印结果如下,可以看到完成了对数组cxk内部成员的遍历操作: image.png 好了,介绍完Interator接口。我们回到解构赋值。

以下这样写都是可以的:

// 多级嵌套: let [c, [[x], k]] = [1, [[2], 3]]; // c = 1, x = 2, k = 3 // 省略某些元素,只为需要的元素提供变量名: let [a, , b] = [1, 2, 3]; // a = 1, b = 3 // 不完全解构: let [x, y] = [1, 2, 3]; // x = 1, y = 2 let [a, [b], c] = [1, [2, 3], 4]; // a = 1, b = 2, c = 4 // 搭配剩余运算符: let [a, ...b] = [1, 2, 3, 4]; // a = 1, b = [2, 3, 4] let [x, y, ...z] = ['a']; // x = 'a', y = undefined, z = [] // 所有可遍历对象皆可进行解构赋值: let [x, y, z] = 'cxk'; // x = 'c', y = 'x', z = 'k' let [w, v, z] = new Set(['c', 'x', 'k']); // w = 'c', v = 'x', z = 'k' 2. 对象

在赋值操作符左边放置一个对象字面量,没有顺序要求。

可以属性名 = 变量名:

let {name, age} = {name: 'cxk', age: 24}; // name = 'cxk', age = 2

也可属性名 ≠ 变量名:

let {name: fullName, age: realAge} = {name: 'fpb', age: 24}; // fullName = 'fpb', realAge = 20

对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。 真正被赋值的是后者,而非前者。

let {name: realName} = {name: 'cxk', age: 24}; // realName = 'cxk' // name: error: name is not defined (name相当于匹配的模式,不能被赋值)

以下这样写都是可以的:

// 多级嵌套: let obj = { p: [ '大家好', {y: 'cxk'} ] }; // x = '大家好', y = 'cxk' let { p: [x, {y}] } = obj; // 注意,这时 p 是"模式",不是变量,因此不会被赋值 // 省略某些元素,只为需要的元素提供变量名: let obj = { p: [ '大家好', {y: 'cxk'} ] }; let { p: [x, { }] } = obj; // x = '大家好' // 不完全解构: let obj = { p: [{y: 'cxk'}] }; let { p: [{y}, x ] } = obj; // x = undefined, y = 'cxk' // 搭配剩余运算符: let {x, y, ...rest} = {a: 1, b: 2, c: 3, d: 4}; // x = 1, y = 2, rest = {c: 3, d: 4} 3. 默认值 (1) 数组 在解构赋值表达式中也可以为数组的任意位置添加默认值。

当指定位置的属性不存在,或者其值为undefined时使用默认值。

let [a = true] = [undefined]; // a = true let [x, y = 'b'] = ['a']; // x = 'a', y = 'b'

当解构模式有匹配结果,且匹配结果是undefined时,会触发默认值作为返回结果。

ES6 内部使用 === 判断一个位置是否有值。所以只有当一个数组成员严格等于undefined,默认值才会生效。

let [x = 3, y = x] = []; // x = 3, y = 3 x 与 y 匹配结果为 undefined,触发默认值:x = 3; y = x = 3 let [x = 3, y = x] = [1]; // x = 1, y = 1 x 正常解构,y 匹配结果undefined ,触发默认值:y = x = 1 let [x = 3, y = x] = [1, 2]; // x = 1, y = 2 x 与 y 正常解构赋值,匹配结果:x = 1,y = 2

注意null和undefined不严格相等。

let [x = 1] = [undefined]; // x = 1 let [x = 1] = [null]; // x = null

如果默认值是一个表达式,那么这个表达式是惰性求值的(只有在用到时,才会求值)

function f() { return 'cxk'; } let [x = f()] = ['fpb']; // x 能取到值 fpb,所以函数 f 不会执行 (2) 对象

语法大多同数组:

let {x = 3} = { }; // x = 3 let {x, y = 5} = {x: 1}; // x = 1, y = 5 let {x: y = 3} = { }; // y = 3

默认值生效的条件依然是属性值严格等于undefined。

let {x = 3} = {x: undefined}; // x = 3 let {x = 3} = {x: null}; // x = null 4. 函数参数

下面代码中,函数getMul的参数表面上是一个数组,但在传入参数时,数组参数就被解构成变量x和y。对于函数内部来说,它能感受到的参数就是x和y。

function getMul([x, y]) { return x * y; } getMul([2, 3]); // 6

也可使用默认值:

function f({x = 4, y = 5} = { }) { // 解构失败即使用默认值 return [x, y]; } f({x: 1, y: 2}); // [1, 2] f({x: 3}); // [3, 5] f(); // [4, 5] 五、使用场景 1. 交换参数的值 let x = 1, y = 2; [x, y] = [y, x]; 2. 从函数返回多个值

函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。

使用解构赋值,取出这些值就非常方便。

// 返回数组 function arr() { return [1, 2, 3]; } let [a, b, c] = arr(); // 返回对象 function obj() { return { a: 1, b: 2 }; } let {x, y} = obj(); 3. 提取Json数据

对获取Json数据中的特定数据尤其方便。

let jsonData = { id: 142857, status: 'OK', data: [1234, 5678] }; let {id, status, data: number} = jsonData; // id = 142857, status = 'OK', number = [1234, 5678]

可以混合解构:

let pra = { name: 'cxk', fund: { start:{ num: 100, isMan: true } }, index: [0,3] }; let { fund: {start:{num}}, index: [start] } = pra; console.log(num); // 100 console.log(start); // 0 4. 可以方便地遍历Map等数据结构

使用for...of可以遍历具有Iterator接口的数据对象。

Map结构具有Iterator接口,配合变量的解构赋值,获取键名和键值就非常方便。

let map = new Map(); map.set('1th', 'fpb'); map.set('2rd', 'cxk'); for (let [key, value] of map) { console.log(key + ": " + value); // 1th: fpb } // 2rd: cxk


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3