变量的解构赋值

ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。

数组的解构赋值

以前,为变量赋值,只能直接指定值:

  1. 1
  2. 2
  3. 3
  1. var a = 1;
  2. var b = 2;
  3. var c = 3;

ES6允许写成下面这样:

  1. 1
  1. var [a, b, c] = [1, 2, 3];

这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值,如果解构不成功,变量的值就等于undefined,下面是一些使用嵌套数组进行解构的例子:

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  1. let [foo, [[bar], baz]] = [1, [[2], 3]];
  2. foo
  3. bar // 2
  4. baz // 3
  5. let [ , , third] = ["foo", "bar", "baz"];
  6. third // "baz"
  7. let [x, , y] = [1, 2, 3];
  8. x
  9. y // 3
  10. let [head, ...tail] = [1, 2, 3, 4];
  11. head
  12. tail // [2, 3, 4]
  13. let [x, y, ...z] = ['a'];
  14. x // "a"
  15. y // undefined
  16. z // []

如果对undefined或null进行解构,会报错。

  1. 1
  2. 2
  1. var [foo] = undefined; // Uncaught TypeError: Cannot match against 'undefined' or 'null'
  2. var [foo] = null; // Uncaught TypeError: Cannot match against 'undefined' or 'null'

这是因为解构只能用于数组或对象。其他原始类型的值都可以转为相应的对象,但是,undefined和null不能转为对象,因此报错。

解构赋值允许指定默认值,注意,ES6内部使用严格相等运算符(===),判断一个位置是否有值。所以,如果一个数组成员不严格等于undefined,默认值是不会生效的

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  1. var [foo = true] = [];
  2. foo // true
  3. [x, y = 'b'] = ['a'] // x='a', y='b'
  4. [x, y = 'b'] = ['a', undefined] // x='a', y='b'
  5. var [x = 1] = [undefined];
  6. console.log(x)
  7. var [x = 1] = [null];
  8. console.log(x) // null
  9. var [x = 1] = [2];
  10. console.log(x) // 2

上面代码中,如果一个数组成员是null,默认值就不会生效,因为null不严格等于undefined,同时2也不严格等于undefined,所以默认值也不会生效。

默认值可以引用解构赋值的其他变量,但该变量必须已经声明。

  1. 1
  2. 2
  3. 3
  4. 4
  1. let [x = 1, y = x] = []; // x=1; y=1
  2. let [x = 1, y = x] = [2]; // x=2; y=2
  3. let [x = 1, y = x] = [1, 2]; // x=1; y=2
  4. let [x = y, y = 1] = []; // ReferenceError

对象的解构赋值

解构不仅可以用于数组,还可以用于对象。

  1. 1
  2. 2
  3. 3
  1. var { foo, bar } = { foo: "aaa", bar: "bbb" };
  2. console.log(foo); // aaa
  3. console.log(bar); // bbb

对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

  1. 1
  2. 2
  1. var { baz } = { foo: "aaa", bar: "bbb" };
  2. console.log(baz) // undefined

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

  1. 1
  2. 2
  3. 3
  1. var { foo: baz } = { foo: "aaa", bar: "bbb" };
  2. console.log(baz) // "aaa"
  3. console.log(foo) // error: foo is not defined

和数组一样,解构也可以用于嵌套结构的对象,在嵌套中,模式是不会被赋值的,只有变量会被赋值。

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  1. var node = {
  2. loc: {
  3. start: {
  4. line: 1,
  5. column: 5
  6. }
  7. }
  8. };
  9. var { loc: { start: { line }} } = node;
  10. console.log(line)
  11. console.log(loc) // error: loc is undefined
  12. console.log(start) // error: start is undefined

如果要将一个已经声明的变量用于解构赋值,必须非常小心。

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  1. var x;
  2. // 错误的写法
  3. {x} = {x: 1};
  4. // 正确的写法
  5. ({x} = {x: 1});
  6. // SyntaxError: syntax error

上面代码的写法会报错,因为JavaScript引擎会将{x}理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免JavaScript将其解释为代码块,才能解决这个问题。

字符串的解构赋值

字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  1. const [a, b, c, d, e] = 'hello';
  2. console.log(a) // "h"
  3. console.log(b) // "e"
  4. console.log(c) // "l"
  5. console.log(d) // "l"
  6. console.log(e) // "o"
  7. let {length : len} = 'hello';
  8. console.log(len) // 5

函数参数的解构赋值

函数的参数也可以使用解构赋值

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  1. function ({x = 0, y = 0} = {}) {
  2. return [x, y];
  3. }
  4. move({x大专栏  ES6学习笔记之变量的解构赋值>: 3, y: 8}); // [3, 8]
  5. move({x: 3}); // [3, 0]
  6. move({}); // [0, 0]
  7. move(); // [0, 0]

上面代码中,函数move的参数是一个对象,通过对这个对象进行解构,得到变量x = 0y = 0的值。如果解构失败,x和y等于默认值。

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  1. function ({x, y} = { x: 0, y: 0 }) {
  2. return [x, y];
  3. }
  4. move({x: 3, y: 8}); // [3, 8]
  5. move({x: 3}); // [3, undefined]
  6. move({}); // [undefined, undefined]
  7. move(); // [0, 0]

上面代码是为函数move的参数指定默认值,而不是为变量xy指定默认值,所以会得到与前一种写法不同的结果。但是undefined就会触发函数参数的默认值。

  1. 1
  2. 2
  1. [1, undefined, 3].map((x = 'yes') => x)
  2. // [ 1, 'yes', 3 ]

不能使用圆括号的情况

  • 变量声明语句中,不能带有圆括号
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  1. // 全部报错
  2. var [(a)] = [1];
  3. var {x: (c)} = {};
  4. var ({x: c}) = {};
  5. var {(x: c)} = {};
  6. var {(x): c} = {};}
  7. var { o: ({ p: p }) } = { o: { p: 2 } };
  • 函数参数中,模式不能带有圆括号
  1. 1
  2. 2
  1. // 全部报错
  2. function f([(z)]) { return z; }
  • 赋值语句中,不能将整个模式,或嵌套模式中的一层,放在圆括号之中
  1. 1
  2. 2
  3. 3
  4. 4
  1. // 全部报错
  2. ({ p: a }) = { p: 42 };
  3. ([a]) = [5];
  4. [({ p: a }), { x: c }] = [{}, {}];

可以使用圆括号的情况

可以使用圆括号的情况只有一种:赋值语句的非模式部分,可以使用圆括号。

  1. 1
  2. 2
  3. 3
  1. [(b)] = [3]; // 正确
  2. ({ p: (d) } = {}); // 正确
  3. [(parseInt.prop)] = [3]; // 正确

上面三行语句都可以正确执行,因为首先它们都是赋值语句,而不是声明语句;其次它们的圆括号都不属于模式的一部分。第一行语句中,模式是取数组的第一个成员,跟圆括号无关;第二行语句中,模式是p,而不是d;第三行语句与第一行语句的性质一致。

用途

  • 交换变量的值
  1. 1
  1. [x, y] = [y, x];

上面代码交换变量x和y的值,这样的写法不仅简洁,而且易读,语义非常清晰。

  • 从函数返回多个值

函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  1. // 返回一个数组
  2. function example() {
  3. return [1, 2, 3];
  4. }
  5. var [a, b, c] = example();
  6. // 返回一个对象
  7. function example() {
  8. return {
  9. foo: 1,
  10. bar: 2
  11. };
  12. }
  13. var { foo, bar } = example();
  • 函数参数的定义

解构赋值可以方便地将一组参数与变量名对应起来。

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  1. // 参数是一组有次序的值
  2. function f([x, y, z]) { ... }
  3. f([1, 2, 3])
  4. // 参数是一组无次序的值
  5. function f({x, y, z}) { ... }
  6. f({z: 3, y: 2, x: 1})
  • 提取JSON数据

解构赋值对提取JSON对象中的数据

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  1. var jsonData = {
  2. id: 42,
  3. status: "OK",
  4. data: [867, 5309]
  5. }
  6. let { id, status, data: number } = jsonData;
  7. console.log(id, status, number) // 42, "OK", [867, 5309]
  • 函数参数的默认值

指定参数的默认值,就避免了在函数体内部再写var foo = config.foo || 'default foo';这样的语句。

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  1. jQuery.ajax = function (url, {
  2. async = true,
  3. beforeSend = function () {},
  4. cache = true,
  5. complete = function () {},
  6. crossDomain = false,
  7. global = true,
  8. // ... more config
  9. }) {
  10. // ... do stuff
  11. };
  • 遍历Map结构

任何部署了Iterator接口的对象,都可以用for…of循环遍历。Map结构原生支持Iterator接口,配合变量的解构赋值,获取键名和键值就非常方便。

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  1. var map = new Map();
  2. map.set('first', 'hello');
  3. map.set('second', 'world');
  4. for (let [key, value] of map) {
  5. console.log(key + " is " + value);
  6. }
  7. // first is hello
  8. // second is world

如果只想获取键名,或者只想获取键值,可以写成下面这样。

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  1. // 获取键名
  2. for (let [key] of map) {
  3. // ...
  4. }
  5. // 获取键值
  6. for (let [,value] of map) {
  7. // ...
  8. }
  • 输入模块的指定方法

加载模块时,往往需要指定输入那些方法。解构赋值使得输入语句非常清晰。

  1. 1
  1. const { SourceMapConsumer, SourceNode } = require("source-map");

文章参考ECMAScript 6 入门

ES6学习笔记之变量的解构赋值的更多相关文章

  1. ES6学习 第二章 变量的解构赋值

    前言 该篇笔记是第二篇 变量的解构赋值. 这一章原文链接: 变量的解构赋值 解构赋值 ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). 解构 ...

  2. ES6 学习笔记(二)解构赋值

    一.数组的解构赋值 1.基本用法 ES6允许按照一定模式从数组和对象中提取值,然后对变量进行赋值,该操作即为解构 如: let [a,b,c]=[1,2,3]; console.log(a,b,c) ...

  3. ES6学习笔记(2)----变量的解构和赋值

    参考书<ECMAScript 6入门>http://es6.ruanyifeng.com/ 变量的解构和赋值 本质上:只要模式匹配,左边的变量就能被赋予右边对应的值 原则: 解构赋值的规则 ...

  4. es6学习2:变量的解构赋值

    一:数组的解构赋值 ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构 let [foo, [[bar], baz]] = [1, [[2], 3]]; foo bar ba ...

  5. ES6学习----let、const、解构赋值、新增字符串、模板字符串、Symbol类型、Proxy、Set

    这篇es6的学习笔记来自于表哥 表严肃,是我遇到过的讲课最通透,英文发音最好听的老师,想一起听课就去这里吧 https://biaoyansu.com/i/hzhj1206 ES6就是JS6,JS的第 ...

  6. ES6系列_3之变量的解构赋值

    ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构. 解构有三种类型: 1.数组的解构赋值 (1)简单的数组解构 以前,我们给变量赋值是直接单个指定值,比如: let a=0; ...

  7. ES6标准入门之变量的解构赋值简单解说

    首先我们来看一看解构的概念,在ES6标准下,允许按照一定模式从数组和对象中提取值,然后对变量进行赋值,这被称作解构,简而言之粗糙的理解就是变相赋值. 解构赋值的规则是,只要等号右边的值不是对象或者数组 ...

  8. ES6学习随笔--字符串模板、解构赋值、对象、循环、函数、Promise、Generrator

    在线编译器:babel.github 在nongjs中使用 'use strict' let a = ; 运行node : node --harmony_destructuring xxx.js 代码 ...

  9. ES6第三节:变量的解构赋值

    ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构.下面我们看实际的例子: 一.数组解构: let [a,b,c] = [1,2,3]; console.log(a); //a ...

随机推荐

  1. HTML学习的一些笔记

    为什么会出现HTML这个标记语言 超文本标记语言 HyperText Markup Language HTML是超文本标记语言,标准通用标记语言的一个应用. "超文本"就是指页面内 ...

  2. debian下通过scp 上传下载文件

    1.上传本地文件到服务器 scp /path/filename username@servername:/path/ 2.从服务器上下载文件 scp username@servername:/path ...

  3. oBike退出新加坡、ofo取消免押金服务,全球共享单车都怎么了?

    浪潮退去后,才知道谁在裸泳.这句已经被说烂的"至理名言",往往被用在一波接一波的互联网热潮中.团购.O2O.共享单车.共享打车.无人货柜--几乎每一波热潮在退去后会暴露出存在的问题 ...

  4. CentOS本地挂载镜像

    title date tags layout CentOS6.5 ISO镜像挂载,创建本地yum源 2018-08-23 Linux post 1.虚拟机挂载光盘选择相应的镜像 2.@#¥%--&am ...

  5. 在select2插件中append下拉选,点击没反应的解决

    今天前端大佬帮我解决了一个棘手的问题:克隆了已有系统的网页,尝试把复制下来的html改造成jsp.基本功能正常,然而点击新增按钮,出来的行无法点击下拉选,控制台也没报错. 项目用的是jeesite2. ...

  6. 003.前端开发知识,前端基础CSS(2020-01-07)

    一.CSS初识 CSS通常称为CSS样式表或层叠样式表(级联样式表),主要用于设置HTML页面中的文本内容(字体.大小.对齐方式等).图片的外形(宽高.边框样式.边距等)以及版面的布局等外观显示样式. ...

  7. kubectl 命令详解

    使用kubectl来管理Kubernetes集群. kubectl命令的选项: 选项 作用 --alsologtostderr[=false] 同时输出日志到标准错误控制台和文件 --api-vers ...

  8. T-shirt

    题目描述 JSZKC is going to spend his vacation!  His vacation has N days. Each day, he can choose a T-shi ...

  9. RHCSA考试(Linux7)

    博主本人平和谦逊,热爱学习,读者阅读过程中发现错误的地方,请帮忙指出,感激不尽 一.设置环境: 请初始化您的考试虚拟机 server0.example.com,将系统的 root 账号密码设置为 12 ...

  10. Visual Studio 2017 Professional 下载

    可以进行Office 2013/2016 VSTO开发 安装平台:Win 7 SP1.Win 10. 下载: VisualStudio2017_Professional.rar