1. 数组的解构赋值

基本用法

let [a, b, c] = [1, 2, 3];

let [a,,c] = [1,2,3];

let [a,...b] = [1,2,3]; // a=1; b=[2,3]

// set 结构也可以
let [x, y, z] = new Set(['a', 'b', 'c']);

// Iterator 接口的也可以
function* fibs(){
  yield 1;
  yield 2;
  yield 3;
  yield 4
}

let [first, second, third] = fibs();
third // 3

默认值
let [a=2] = [1];

若值为全等 undefined, 则才为默认值
let [a=2] = [undefined]; // a=2
let [a=2] = [null]; //a = null
let [a=2] = null; // 报错, 如果模式不是数组, 因为会两边不匹配
let [a=2] = undefined; // 报错

若默认值是一个表达式, 那么这个表达式是 惰性求值, 只有用到的时候才会求值
function f(){
  console.log('fffff'); // 这里不会执行
}
let [a=f()] = [1];
a; // 1

// 相当于执行了下面
if( [1][0] === undefined ){
  a = f();
}else{
  a = 1;
}

2. 对象的解构赋值

let {a=3} = {a: 1};
a; // 1

其实相当于:
let {a: a=3} = {a: 1};
// 有点类似于下面的写法
let _temp = {a: 1};
let a = _temp.a || 3;

解构赋值给空数组和空对象

let [a=3] = {} // ?会报错: Uncaught TypeError: undefined is not a function
let {a=3} = [] // 正确 a = 3;

下面的两种写法是一样的, 数组元素是按次序, 变量的取值由它对应的属性名决定。
let {a, b} = {a: 1, b: 2}
let {b, a} = {a: 1, b: 2}

如果变量名与属性名不一致, 写成下面这样, a 是匹配的模式, c 才是变量
let {a:c} = {a: 1, b: 2}
c; //1

说明对象的解构赋值是下面形式:
let {a, b} = {a: 1, b: 2};
// 等价于下面
let {a:a, b:b} = {a: 1, b: 2}

对象也可以进行嵌套
let {a: [{b}, c]} = {a: [{b: 2}, 3]}

a; // undefined
b; // 2
c; // 3

嵌套赋值例子:
let obj = {};
let arr = [];

( {a: obj.q, b: arr[0]} = {a: 1, b: 2} );
obj; // {q: 1}
b; // [2]

解构也可以指定默认值, 也是必须 === undefined
let { a=3 } = {a: 1};
a; //1

let { a=3 } = {a: null};
a; //null

let {a=4} = {a: undefined};
a; // 4

如果解构失败,变量的值等于undefined
let {a} = {b: 2};
a; // undefined

如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错。
// 报错
let {foo: {bar}} = {baz: 'baz'};
相当于:
let _temp = {baz: 'baz'};
{bar} = _temp.foo;
bar = _temp.foo.bar;

已经声明的变量用于解构赋值, 会将 {x}理解成一个代码块 而不是一个语句, 所以要有括号
let x;
{x} = {x: 1}; // Uncaught SyntaxError: Unexpected token =

let x;
({x} = {x: 1}); // 正确

{foo} = {foo: 1}; // 若不用let 也是正确的, foo 直接挂载到 window 下

3. 字符串的解构赋值
// 字符串转换成 类似数组
const [a,b] = 'hello';
a; // h
b; // e

// 字符串类似对象, 它有一个length 的属性
let {length : len} = 'hello';

4. 数值和布尔值的解构赋值
数值和布尔值都会转好成 包装对象

// 相当于s = 123.toStirng
let {toString: s} = 123;

// 相当于 s = true.toString
let {toString: s} = true;

解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。
由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。

let {a: 1} = null; // error
let {a: 1} = undefined; // error

5. 函数参数的解构赋值
function add([x, y]){
  return x + y;
}

add([1, 2]); // 3
相当于 [x, y] = [1, 2];

对于 map
// [5, 10]
[1, 2].map( (a) => a *5 );

// [3, 7]
[[1,2], [3,4]].map( ([a,b]) => a+ b )

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

// 只有当传递的参数为undefined 或不传参数的时候, 才会执行 {a, b} = {a: 1, b: 3}
function move({a, b} = {a: 1, b: 2}){
return [a,b]
}
move({a: 3, b: 4}); // [3, 4]; 等价 {a, b} = {a: 3, b: 4}
move({a: 3}); // [3, undefined]; 等价 {a, b} = {a: 3}
move({}); // [undefined, undefined]; 等价 {a, b} = {}
move([]); // [undefined, undefined]; 等价 {a, b} = []
move(null); // 报错; 等价 {a, b} = null
move(); // [1, 2]; 等价 {a, b} = {a: 1, b: 2}
move(undefined); // [1, 2]; 等价 {a, b} = {a: 1, b: 2} // 同上面道理
function move({x = 0, y = 0} = {x: 100, y: 200}) {
return [x, y];
} move({x: 3, y: 4}); // [3, 4]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [100, 200]

undefined就会触发函数参数的默认值。
[1, undefined, 3].map( (a = 2) => a ); // [1, 2, 3]

6. 圆括号的问题
使用圆括号的情况

赋值语句并且非模式部分,可以使用圆括号。
({ p: (d) } = {p: 3}); // 正确, 这里d是非模式, p是模式, 最后 d = 3
let ({ p: (d) } = {}); // 错误, 因为是声音语句

[(b)] = [3]; // 正确, 说明这个b是非模式部分, 有点类似于 [0:(b)] = [3], 直接这么写会报错
({(a)} = {a: 3}); // 错误, 说明是这么执行 {(a): a} = {a: 3}; 括号加在了 a的模式部分

7.用途

1) 交换变量的值
let x=1;
let y=2;
[x,y] = [y,x];

2) 从函数返回多个值
function f(){
  return {
    a: 1,
    b: 2
  }
}

let {a, b} = f();

function f(){
  return [2, 3]
}
let [a, b] = f();

3) 函数参数的定义
function f([x, y, z]){
  console.log(arguments[0]); // [1,2,3]
  console.log(x, y, z);
}
f([1,2,3]);

function f({x, y, z}){
  console.log(arguments[0]); // arguments[0] 其实就是 {x: 1, y:2, z: 3}
  console.log(x, y, z); // x = 1, y = 2, z = 3;
}
f({x: 1, y: 2, z: 3});

4) 提取JSON数据
let o = {
  a: 1,
  b: 2
}

let {a, b} = o;

5) 函数参数的默认值
function f({x = 2, y = 3}){
  console.log(x, y);
}
f({});
f(); // error, 必须至少传入空对象, 否则会报错

6)遍历Map结构
var map = new Map();
map.set('first', 'hello');
map.set('second', 'world');

for(let item of map){
  console.log(item); // item 分别输出 ["first", "hello"], ["second", "world"]
}

所以可以写成:
for(let [key, value] of map){
  cnosole.log(key, value);
}

// 获取key 的值
for( let [key] of map){
  console.log(key);
}

// 获取value 的值
for( let [, value] of map){
  console.log(value);
}

7)输入模块的指定方法
const {a, b} = require('./test2')
import {a, b} from './test2';

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

  1. 03 | 变量的解构赋值 | es6

    变量的解构赋值 数组的解构赋值 基本用法 ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). 以前,为变量赋值,只能直接指定值. let a ...

  2. es6之变量的解构赋值

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

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

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

  4. ES6学习笔记之变量的解构赋值

    变量的解构赋值 ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构. 数组的解构赋值 以前,为变量赋值,只能直接指定值: 1 2 3 var a = 1; var b = 2; ...

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

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

  6. ES6 变量的解构赋值

    数组的解构赋值     var [a,b,c] = [1,2,3];    左边是变量,右边是值,根据数据结构一一对应 只要等号两边的模式相同,左边的变量就会被赋予右边对应的值,必须模式相同 如果等号 ...

  7. ES6 - 变量的解构赋值学习笔记

    变量的解析赋值 数组的解析赋值 es6允许按照一定的模式,从数组和对象中提取值,对变量进行赋值,这就称为解构. var a = 1; var b = 2; var c = 3; //在es6中允许写成 ...

  8. ES6学习之变量的解构赋值

    前言:什么是ES6?ECMAScript 6(简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了.其中相比较于ES5新增了诸多的特性,并且ES6可转换为ES5的语法.- ...

  9. es6笔记(3) 变量的解构赋值

    基本概念 本质上是一种匹配模式,只要等号两边的模式相同,那么左边的变量就可以被赋予对应的值. // 以往定义接个变量的时候,需要这样 var a = 1, b = 2, c = 3; // 使用ES6 ...

随机推荐

  1. 超越icon font

    很久以前,我们如何使用图标? 1.切图 2.拼合(Sprites) 原始社会啊! 后来CSSGagagrunt-css-sprite 字体图标 相见不曾相识 Emoji绘文字 iconfont.cn直 ...

  2. 【BZOJ】3998: [TJOI2015]弦论

    [题意]给定长度为n的小写字母字符串S,求第k小子串.n<=5*10^5. 给定T,T=0时不同位置的相同子串算一个,T=1时算多个. [算法]后缀自动机 [题解]对S建立SAM,T=0则每个节 ...

  3. HDU 2050 折线分割平面 (数学)

    题目链接 Problem Description我们看到过很多直线分割平面的题目,今天的这个题目稍微有些变化,我们要求的是n条折线分割平面的最大数目.比如,一条折线可以将平面分成两部分,两条折线最多可 ...

  4. 记一次诡异的bug调试——————关于JDK1.7和JDK1.8中HashSet的hash(key)算法的区别

    现象: 测试提了一个bug,我完全复现不了,但是最吊诡的是在其他人的机器上都可以复现.起初以为是SVN合并后出现的冲突,后来经过对比法排查: step 1: 我本地开两个jetty,一个跑合并之前的版 ...

  5. 发行NEO的NEP-5合约代币

    NEO常见的资产有三种 TOKEN (全局资产) Share (全局资产,股份 ) NEP-5 (合约代币,相当于ETH的ERC20) NEP-5 合约代码 https://github.com/AN ...

  6. Linux 编译 apr-util 时报错

    前言 Apache 2.4 以后的版本不再自带 APR 库(Apache Portable Runtime,Apache 可移植运行库),所以在安装 Apache 之前需要手动下载安装 APR 库. ...

  7. Mybatis的初步使用

    MyBatis 是当下最流行的持久层框架,也是ORM框架,本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google ...

  8. LeetCode862. Shortest Subarray with Sum at Least K

    Return the length of the shortest, non-empty, contiguous subarray of A with sum at least K. If there ...

  9. Ubuntu下Node.js开发起步之旅

    因为忙其它的事,把Node.js的学习放下了快两个月了,世事变化还真快,发现很多东东都改变了,express已经升级到4.x了,变化还不小! 我原来的学习过程是在VirtualBox中安装Ubuntu ...

  10. lr场景运行报错的解决方法