摘要:允许按照一定的模式,从数组和对象中提取值,对变量进行赋值,这个被称为解构。对象的解构赋值机制是先找到同名属性,然后再赋值给对应的变量。解构赋值对提取对象中的数据,尤其有用。结构原生支持接口,配合变量的解构赋值,获取键名和键值就非常方便。
ES6 允许按照一定的模式,从数组和对象中提取值,对变量进行赋值,这个被称为解构。
解构的用途
1、数组解构赋值交换变量的值
从函数返回多个值
函数参数的定义
提取JSON数据
函数参数的默认值
遍历Map结构
输入模块的指定方法
(1) 完全解构,这种写法属于 “模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。如:
let [foo, [[bar], baz]] = [1, [[2], 3]]; foo // 1 bar // 2 baz // 3 let [ , , third] = ["foo", "bar", "baz"]; third // "baz" let [x, , y] = [1, 2, 3]; x // 1 y // 3 let [head, ...tail] = [1, 2, 3, 4]; head // 1 tail // [2, 3, 4] let [x, y, ...z] = ["a"]; x // "a" y // undefined z // []
(2) 不完全解构,等号左边的模式只匹配到一部分等号右边的数组。这种情况下依然可以解构成功。
let [x, y] = [1, 2, 3]; x // 1 y // 2 let [a, [b], d] = [1, [2, 3], 4]; a // 1 b // 2 d // 4
如果等号的右边不是数组的话,就会报错。
// 报错 let [foo] = 1; let [foo] = false; let [foo] = NaN; let [foo] = undefined; let [foo] = null; let [foo] = {};
事实上,只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值。
function* fibs() { let a = 0; let b = 1; while (true) { yield a; [a, b] = [b, a + b]; } } let [first, second, third, fourth, fifth, sixth] = fibs(); sixth // 5
2、对象的解构赋值上面代码中,fibs是一个 Generator 函数,原生具有 Iterator 接口。解构赋值会依次从这个接口获取值。
对象解构赋值和数组的解构赋值不一样。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
//具体版 let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" }; //简写版 let { bar, foo } = { foo: "aaa", bar: "bbb" }; foo // "aaa" bar // "bbb" let { baz } = { foo: "aaa", bar: "bbb" }; baz // undefined
如果变量名与属性名不一致,必须写下面这样。
var { foo: baz } = { foo: "aaa", bar: "bbb" }; baz // "aaa" let obj = { first: "hello", last: "world" }; let { first: f, last: l } = obj; f // "hello" l // "world"
对象的解构赋值机制是 先找到同名属性,然后再赋值给对应的变量。前者是匹配的模式,后者才是真正的变量。真正被赋值的应该是变量。
let { foo: baz } = { foo: "aaa", bar: "bbb" }; baz // "aaa" foo // error: foo is not defined var node = { loc: { start: { line: 1, column: 5 } } }; var { loc: { start: { line }} } = node; line // 1 loc // error: loc is undefined start // error: start is undefined //这由于只有line是变量,loc和start都是模式,所以不会被赋值啦。
如果解构失败,变量的值等于undefined。
let {foo} = {bar: "baz"}; foo // undefined
如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错。等号左边对象的foo属性,对应一个子对象。该子对象的bar属性,解构时会报错。原因很简单,因为foo这时等于undefined,再取子属性就会报错,请看下面的代码。如:
let {foo: {bar}} = {baz: "baz"}; // 报错3、字符串的解构赋值
字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。
const [a, b, c, d, e] = "hello"; a // "h" b // "e" c // "l" d // "l" e // "o" let {length : len} = "hello"; len // 54、函数参数解构赋值
函数参数的解构也可以使用默认值
function add([x, y]){ return x + y; } add([1, 2]); // 3 function move({x = 0, y = 0} = {}) { return [x, y]; } move({x: 3, y: 8}); // [3, 8] move({x: 3}); // [3, 0] move({}); // [0, 0] move(); // [0, 0]5、默认值
(1)解构赋值允许指定默认值。因为ES6内部使用严格的相等运算符(===),如果一个数组成员不严格等于undefined,默认值不会生效的。如:
let [x = 1] = [undefined]; x // 1 let [x = 1] = [null]; x // null, 因为null不严格等于 undefined
(2)如果默认值是一个表达式的话,那么表达式是惰性求值的,即只有在用到的时候,才会求值。
function f() { console.log("aaa"); } let [x = f()] = [1]; //等价于 let x; if ([1][0] === undefined) { x = f(); } else { x = [1][0]; }
因为x能取到值,所以函数f根本不会执行。
6、具体用途(1)交换变量的值
let x = 1; let y = 2; [x, y] = [y, x];
(2)从函数返回多个值
// 返回一个数组 function example() { return [1, 2, 3]; } let [a, b, c] = example(); a // 1 b // 2 c // 3 // 返回一个对象 function example() { return { foo: 1, bar: 2 }; } let { foo, bar } = example(); foo // 1 bar // 2
(3)函数参数的定义
// 参数是一组有次序的值 function f([x, y, z]) { ... } f([1, 2, 3]); // 参数是一组无次序的值 function f({x, y, z}) { ... } f({z: 3, y: 2, x: 1});
(4)提取JSON数据 ,快速提取 JSON 数据的值。解构赋值对提取JSON对象中的数据,尤其有用。
let jsonData = { id: 42, status: "OK", data: [867, 5309] }; let { id, status, data: number } = jsonData; console.log(id, status, number); // 42, "OK", [867, 5309]
(5)函数参数的默认值。 指定参数的默认值,就避免了在函数体内部再写var foo = config.foo || "default foo";这样的语句。
jQuery.ajax = function (url, { async = true, beforeSend = function () {}, cache = true, complete = function () {}, crossDomain = false, global = true, // ... more config }) { // ... do stuff };
(6)遍历Map结构, 任何部署了Iterator接口的对象,都可以用for...of循环遍历。Map结构原生支持Iterator接口,配合变量的解构赋值,获取键名和键值就非常方便。
var map = new Map(); map.set("first", "hello"); map.set("second", "world"); for (let [key, value] of map) { console.log(key + " is " + value); } // first is hello // second is world // 获取键名 for (let [key] of map) { // ... } // 获取键值 for (let [,value] of map) { // ... }
(7)输入模块的指定方法加载模块时,往往需要指定输入哪些方法。解构赋值使得输入语句非常清晰。
const { SourceMapConsumer, SourceNode } = require("source-map");
参考文章
http://es6.ruanyifeng.com/#do...
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/82516.html
摘要:另外对于已经声明的变量进行解构赋值时,要非常小心。因此在行首加,将其强制转化为表达式执行。由于和无法转为对象,所以对它们进行解构赋值,都会报错。 let和const let和const是es6新增的两个变量声明关键字,与var的不同点在于: (1)let和const都是块级作用域,在{}内有效,这点在for循环中非常有用,只在循环体内有效。var为函数作用域。 (2)使用let和con...
摘要:比如上面展示的情况都是可以联合使用的比如对象的解构赋值对象的解构赋值是基于属性的。当给已存在的变量解构赋值时,注意加这是由于如果不加会把左边看成一个代码块,会报错。注意事项数组的解构赋值中,使用的变量必须放在最后。 解构赋值 解构赋值是一个听起来比较高大上的特性,但按我的理解,它就是一种语法糖。它并没有赋予js更强大的能力,只是让赋值操作更加的灵活,效率。 在es6之前,赋值操作需要=...
摘要:前言前言该篇笔记是第二篇变量的解构赋值。这一章原文链接变量的解构赋值解构赋值解构赋值允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。对象的解构赋值是根据对象值进行匹配。前言该篇笔记是第二篇 变量的解构赋值。这一章原文链接: 变量的解构赋值解构赋值ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。解构赋值是对赋值运...
摘要:前言该篇笔记是第二篇变量的解构赋值。这一章原文链接变量的解构赋值解构赋值允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。对象的解构赋值是根据对象值进行匹配。 前言该篇笔记是第二篇 变量的解构赋值。 这一章原文链接: 变量的解构赋值解构赋值ES6 允许按照一定模式,从数组和对象中提取值,对...
摘要:数组的解构赋值特点根据数据的下标来赋值的,有次序。模式能够匹配起来,如长度为数值和布尔值的解构赋值解构赋值的规则是只要等号右边的值不是对象或数组,就先将其转为对象。布尔值解构赋值为字符串的一种。在很多独立细小的方面,解构赋值都非常有用。 1、解构赋值简介 官方解释:按照一定的模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。 举个例子,想获取数组中...
摘要:它是一个通用标准,奠定了的基本语法。年月发布了的第一个版本,正式名称就是标准简称。结语的基本扩展还有一些没有在这里详细介绍。 前言 ES6标准以及颁布两年了,但是,好像还没有完全走进我们的日常开发。这篇文章从ES6的基本类型扩展入手,逐步展开对ES6的介绍。 ECMAScript和JavaScript JavaScript是由Netscape创造的,该公司1996年11月将JavaSc...
阅读 1330·2019-08-30 15:44
阅读 2079·2019-08-30 11:04
阅读 464·2019-08-29 15:17
阅读 2479·2019-08-26 12:12
阅读 3105·2019-08-23 18:09
阅读 891·2019-08-23 15:37
阅读 1502·2019-08-23 14:43
阅读 2889·2019-08-23 13:13