1. 数组的解构赋值

解构: ES6 中允许按照一定的模式从数组和对象中提取值,然后对变量进行赋值,这被称为解构(Destructuring).

1. 基本用法

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

  • 完全解构
let [a, b, c] = [1, 2, 3];
console.log(a); // 输出1
let [a, b] = [1];
console.log(b); // 解构不成功时返回undefined
  • 不完全解构

    等号左边只匹配到等号右边的一部分。

    let [a, [b], c] = [1, [2, 3], 4];
    console.log(b); // 输出2,只匹配到右边的右边数组[2, 3]中的2
  • 不能解构情况

    如果等号右边不是可遍历的解构,或者说等号右边的值或是转换为对象以后也不具备 Iterator 接口,那么就会解构失败。

    let [a] = 1;
    let [a] = false;
    let [a] = NaN;
    let [a] = undefined;
    let [a] = null;
    let [a] = {}

    总结:事实上,只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值。

2. 默认值

解构赋值允许指定默认值。

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

let [a = 2] = [null];
// a = null
let [a = 2] = [];
// a = 2

如果默认值是一个表达式,那么这个表达式是惰性求值的

function f() {
return 2;
}
let [a = f()] = [1];
// a = 1, f函数不会执行 let [a = f()] = [];
// a = 2, f函数会执行

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

let [x = 1, y = x] = [];
// x = 1, y = 1
let [x = y, y = 1] = [];
// ReferenceError,在使用变量y时还并没有声明

2. 对象的解构赋值

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

举例说明:

let {foo:bar} = {foo:"aaa"};
console.log(bar); // bar = "aaa"
console.log(foo); // ReferenceError, foo is not defined
console.log({foo:bar}.foo); // {foo:bar}.foo = "aaa"

上面代码中 foo 是匹配的模式,通过 foo 匹配到对象 {foo:bar}foo 属性的值( bar 变量),然后将值赋给 bar 变量,这样对象 {foo:bar}foo 属性就有值了,即 bar 的值 "aaa".

// 实际上
let {foo1, foo2} = {foo1:"aaa", foo2:"bbb"};
// 是下面语句的简写形式
let {foo1:a, foo2:b} = {foo1:"aaa", foo2:"bbb"};

对象的解构也可以指定默认值,默认值生效的条件是,对象的属性值严格等于undefined

let {x = 3} = {x: undefined};
// x = 3
// 上面的语句等价于
let {x:x = 3} = {x: undefined};
// x = 3
// {x:x = 3} = 3 let {x = 3} = {x: null};
// x = null

如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错

let {foo: {bar}} = {bar: 'bar'};
// 报错,因为foo = {bar} = undefined,{bar}对象中的bar属性在解构时会报错,因为{bar}是undefined,undefined是不能转换为对象的,对undefined取bar属性会报错。
// 和下面的代码原理一样:
let obj = {bar: "bar"};
obj.foo.bar // 报错,因为obj.foo = undefined,对undefined取属性会报错。
"bar".foo // undefined,不会报错,因为字符串可以转换为对象

在将已经声明的变量进行解构赋值时,要注意解构赋值语句不能直接写在行首

let x;
{x} = {x: 1}; // 报错,这个地方不是很懂
// 书上的解释是:JS引擎将{x}理解成一个代码块,从而发生语法错误。
// 若想避免这个错误,可以这样写:
({x} = {x: 1});

3. 字符串的解构赋值

字符串可以解构赋值是因为字符串可以转换成一个类似数组的包装对象。

let [a, b, c, d, e] = "hello";
// a = 'h' b = 'e' c = 'l' d = 'l' e = 'o'

由于类似数组的包装对象有一个 length 属性,因此在解构赋值时可以利用这个属性。

let {length: len} = 'hello';
// len = 5

4. 数值和布尔值的解构赋值

解构赋值时,如果等号右边是数值或布尔值,则会先转为对象

let {toString: s} = 123;
console.log(s === Number.prototype.toString) // true

数值 123 被转换为对象,数值对象中有 toString 方法,与 toString 匹配,变量 s 中存储的是 toString 方法,该方法就是 Number 原型对象中的 toString 方法。

5. 函数参数的解构赋值

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

function f({x = 0, y = 0} = {}) {
return {x, y};
}
console.log(f({x: undefined, y: 1}));
// 输出: {0, 1}

详细过程:调用函数f后,{x = 0, y = 0}={x:undefined,y:1}

由于x是undefined,故x使用默认值即x=0,由于y:1故通过解构赋值后y=1.

之前的误区:注意是解构赋值,并不是对象之间的赋值。

再看下面这个例子:

function f({x, y} = {x: 0, y: 0}) {
return {x, y};
}
console.log(f({x: undefined, y: 1}));
// 输出: {undefined, 1}
// 调用函数后,{x,y}={x:udefined,y:1},解构赋值后x=undefined,y=1
console.log(f({x: 1, y: 1}));
// 输出: {1, 1}
// 调用函数后,{x,y}={x:1,y:1},解构赋值后x=1,y=1
console.log(f({}));
// 输出: {undefined, undefined}
// 调用函数后,{x,y}={}={undefined,undefined},解构赋值后x=undefined,y=undefined
console.log(f());
// 输出: {0, 0} 当不传递实参时,形参的值是原有的值
// 调用函数后,{x,y}={x:0,y:0},解构赋值后x=0,y=0

再次重申一下 {x,y}={x:1,y:2} 这种形式是解构赋值,千万不要理解成对象之间的赋值!

6. 圆括号问题

对于编译器而言,一个式子到底是模式还是表达式,没有办法一开始就知道,必须解析到(或解析不到)等号才能知道

  • 不能使用圆括号的情况

    1. 变量声明语句
    2. 函数参数
    3. 赋值语句表达式
  • 可以使用圆括号的情况

    赋值语句中的非模式部分可以使用圆括号。

    [(a)] = [3]; // a并不是模式
    ({ p: (d) } = {}); // p是模式,d并不是模式

建议:无论什么情况都尽量不要在模式中使用圆括号

7. 解构赋值的作用

  1. 交换变量的值

    let a = 1;
    let b = 2;
    [a, b] = [b, a];
  2. 方便处理函数返回值

    function f([x, y]) {
    return [x+1, y+2];
    }
    let [a, b] = f([1, 1]);
  3. 函数参数定义

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

    function f1({x, y, z}){
    return x+y+z;
    }
    f1({y: 1, z: 2, x: 3 }); // 可以做到实参没有次序
  4. 提取JSON数据

    可以很方便地从JSON中提取需要的数据。

    let JSON = {
    name: "happyCoding1024",
    age: 18,
    hobby: "coding"
    }
    let [name, age, hobby] = JSON;
  5. 函数参数默认值

    非常简化方便地使用函数参数默认值。

    function f([x=0,y=0] = []){
    return x+y;
    }
    f([]); // 当传入的是undefined时,就会使用默认值
  6. 遍历Map结构

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

    let map = new Map();
    map.set('first', 'hello');
    map.set('second', 'world');
    for (let [key, value] = map){
    console.log(key + "is" + value);
    }
  7. 输入模块的指定方法

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

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

ES6 中变量的解构赋值的更多相关文章

  1. ES6中变量的解构赋值

    1.数组的解构赋值 基本用法 ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). 输出: 上面代码表示,可以从数组中提取值,按照对应位置,对变 ...

  2. es6之变量的解构赋值

    es5中通常我们声明变量都是以下的方式: var a = 10; var b = 20; var c = 30; //或者 var a = 10,b = 20,c = 30; //或者 var arr ...

  3. es6分享——变量的解构赋值

    变量的解构赋值:ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). 以前的写法: var a = 1; var b = 2; es6允许的写法 ...

  4. ES6 继续 变量的解构赋值

    春节放假这几天,感觉跟梦一样,瞬间就过去了.现在上班的前几天,都感觉有点不真实,不过看到口袋里的钱,就知道,是真真实实的度过了这个假期. 现在得开始重新工作了: 变量的解构赋值 ES6 允许按照一定模 ...

  5. ES6入门——变量的解构赋值

    1.数组的解构赋值 以前为变量复制,只能直接指定值.现在ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). 本质上,这种写法属于模式匹配,只要等 ...

  6. es6系列-变量的解构赋值

    git地址: https://github.com/rainnaZR/es6-study/tree/master/src/destructuring 变量的解构赋值 变量的解构赋值: 数组, 对象, ...

  7. ES6基础-变量的解构赋值

    作者 | Jeskson 来源 | 达达前端小酒馆 解构赋值: 数组的解构赋值,对象的解构赋值,字符串的解构赋值,数值与布尔值的解构赋值,函数参数的解构赋值. 开发环境准备: 编辑器,VS Code, ...

  8. 【ES6】变量的解构赋值

    1. 数组 var [a, b, c] = [1, 2, 3]; let [a, [b], d] = [1, [2, 3], 4]; 默认值生效的条件是,对象的属性值严格等于undefined. [x ...

  9. js中 变量的解构赋值

    es6新特性, 提取数组或对象中的值,按照对应位置, 为变量赋值. let [a, b, c] = [1, 2, 3]; 交换变量的值变得容易 let x = 1; let y = 2; [x, y] ...

随机推荐

  1. Vue中的better-scroll插件

    Vue中的better-scroll插件 在需要的文件中添加 import BScorll from 'better-scroll'; 引用的示例代码: let scroll = new BScrol ...

  2. centos部署jeecms

    首先下载安装包apache-tomcat-8.5.40.tar.gz jdk-8u211-linux-x641.rpm jeecmsv9.war 已经在WEB-INF/config/jdbc.prop ...

  3. jdk11下载安装及环境变量配置

    jdk11下载安装及环境变量配置 官网地址:https://www.oracle.com/technetwork/java/javase/downloads/jdk11-downloads-50666 ...

  4. PHP 类与对象 全解析方法

    1.类与对象 对象:实际存在该类事物中每个实物的个体.$a =new User(); 实例化后的$a 引用�php的别名,两个不同的变量名字指向相同的内容 封装: 把对象的属性和方法组织在一个类(逻辑 ...

  5. [转]Visual Studio 2010生成解决方案时,提示磁盘空间不足!

    最近几天,使用VS调试时总是出现提示:磁盘空间不足.我觉得可能有两种可能:    1.系统盘已被木马侵袭.历时4小时的全盘扫描没有病毒提示,只好删除了一些不必要的软件:    2.使用VS2010调试 ...

  6. XAMPP:继MAMP之后,Mac OS X平台下又一款帮你快速搭建服务器环境软件

    之前,有很多人都有打算在自己的Mac OS下搭建一个本地测试用的Apache+PHP+MySQL网络服务器环境. 在目前而言至少有3种办法可以实现这一点: 通过Xcode开发者套件和php.Apach ...

  7. jeecms 修改后台访问路径

       版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq_30553235/article/details/74971414 我使用的是jeecms ...

  8. csdn vip文章:Unity游戏开发-小游戏-非常简单的游戏-unity-

    原文https://blog.csdn.net/qq_20484877/article/details/81841190 1*创建物体 Create菜单下 3D Object菜单下Cube 1.1设置 ...

  9. tensorflow高效地推导pb模型,完整代码

    from matplotlib import pyplot as plt import numpy as np import os import six.moves.urllib as urllib ...

  10. LA5713 Qin Shi Huang's National Road System

    题目大意:秦始皇要在n个城市之间修筑一条道路使得任意两个城市均可连通.有个道士可以用法力帮忙修一条路.秦始皇希望其他的道路总长B最短且用法术连接的两个城市的人口之和A尽量大,因此下令寻找一个A / B ...