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';

最新文章

  1. sqlserver中创建包含事务的存储过程
  2. imageNamed、imageWithContentsOfFile、imageWithData
  3. 使用Mac的AppleScritp调用控制台的方式
  4. threadlocal精髓是为每一个线程保证一个共享对象,保证一个,保证是同一个
  5. linux grep和正则表达式
  6. AndroidUI 视图动画-自定义动画效果 (Animation)
  7. 【Android Developers Training】 83. 实现高效网络访问来优化下载
  8. InnoDB关键特性之自适应hash索引
  9. 51nod 1126 求递推序列的第N项 思路:递推模拟,求循环节。详细注释
  10. Android之MaterialDesign应用技术
  11. vue静态文件处理
  12. Java 容器源码分析之 Map
  13. IDEA插件(Android Studio插件)开发示例代码及bug解决
  14. Intellij idea安装
  15. (转)synchronized和lock的区别
  16. Eclipse的Servers视图中无法添加Tomcat
  17. 【微信小程序】tabBar的显示问题
  18. hasura graphql server event trigger 试用
  19. Understanding Safari Reader
  20. Python isupper() 方法

热门文章

  1. Centos7系统环境下Solr之Java实战(二)制定中文分析器、配置业务域
  2. json属性名为什么要双引号?
  3. text-align: justify;不能均匀分布问题
  4. 在Java中,你真的会日期转换吗
  5. 【leetcode 简单】 第三十五题 环形链表
  6. Openflow Plugin学习笔记1
  7. D - Binary Lexicographic Sequence URAL - 1081 (贪心)
  8. MySQL创建相同表和数据命令
  9. java获取weblogic应用运行路径
  10. Ubuntu 下查看已安装的软件