[TOC]
>[success] # 数组的解构赋值
<br/>
>[success] ## 基本用法
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。
以前,为变量赋值,只能直接指定值。
~~~
let a = 1;
let b = 2;
let c = 3;
~~~
ES6 允许写成下面这样,这种写法为匹配模式,只要`=`两边的模式相同,左边的变量就会被赋予对应的值。
~~~
let [a, b, c] = [1, 2, 3];
console.log( a ) // 1
console.log( b ) // 2
console.log( c ) // 3
~~~
<br/>
>[success] ## 嵌套数组
第一种写法,按照数组的格式来嵌套就可以取出来对应的数据
~~~
let [foo, [[bar], baz]] = [1, [[2], 3]];
console.log( foo ) // 1
console.log( bar ) // 2
console.log( baz ) // 3
~~~
第二种写法,即使左侧的一些值未定义逗号分隔还在,也是可以的
~~~
let [ , , third] = ["foo", "bar", "baz"];
console.log( third ) // "baz"
~~~
第三种写法,配合扩展运算符
~~~
let [head, ...tail] = [1, 2, 3, 4];
console.log( head ) // "1"
console.log( tail ) // [2, 3, 4]
~~~
<br/>
>[danger] ## 错误写法
如果解构不成功,变量的值就等于`undefined`。
~~~
let [x, y, ...z] = ['a'];
console.log( x ) // "a"
console.log( y ) // undefined
console.log( z ) // []
~~~
以下两种情况都属于解构不成功,foo的值都会等于undefined。
另一种情况是不完全解构,即等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功。
~~~
let [foo] = [];
let [bar, foo] = [1];
~~~
以上两种情况都属于解构不成功,foo的值都会等于undefined。
~~~
let [x, y] = [1, 2, 3];
console.log( x ) // 1
console.log( y ) // 2
let [a, [b], d] = [1, [2, 3], 4];
console.log( a ) // 1
console.log( b ) // 2
console.log( d ) // 4
~~~
上面两个例子,都属于不完全解构,但是可以成功。
~~~
// 报错
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};
~~~
上面的语句都会报错,因为等号右边的值,要么转为对象以后不具备 Iterator 接口(前五个表达式),要么本身就不具备 Iterator 接口(最后一个表达式)。
<br/>
>[success] ## 默认值
解构赋值允许指定默认值,可以赋值默认值的位置是等号的左面(let [a='3'] = [])
~~~
let [foo = true] = [];
console.log( foo ) // true
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
~~~
注意,ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,如果一个数组成员不严格等于undefined,默认值是不会生效的。
~~~
let [x = 1] = [undefined];
console.log( x ) // 1
let [x = 1] = [null];
console.log( x ) // null
~~~
~~~
function f() {
console.log('aaa');
}
let [x = f()] = [1];
~~~
上面代码中,因为x能取到值,所以函数f根本不会执行。上面的代码其实等价于下面的代码。
~~~
let x;
if ([1][0] === undefined) {
x = f();
} else {
x = [1][0];
}
~~~
默认值可以引用解构赋值的其他变量,但该变量必须已经声明。
~~~
let [x = 1, y = x] = []; // x=1; y=1
let [x = 1, y = x] = [2]; // x=2; y=2
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = []; // ReferenceError
~~~
上面最后一个表达式之所以会报错,是因为x用到默认值y时,y还没有声明。
- Javascript基础篇
- Array数组
- 数组插入值
- filter()
- forEach()
- push()
- pop()
- unshift()
- shift()
- valueOf()
- 面向对象思想
- Javascript 面向对象编程(一):封装
- Javascript面向对象编程(二):构造函数的继承
- Javascript面向对象编程(三):非构造函数的继承
- 解构
- 数组的解构赋值
- 对象的解构赋值
- 函数参数解构
- 字符串的解构赋值
- 数值和布尔值的解构赋值
- 圆括号问题
- 字符串.
- split()
- charAt()
- charCodeAt()
- concat()
- indexOf()
- lastIndexOf()
- match()
- replace()
- includes()
- 初识递归
- 渲染ul-li树形结构
- 异步函数解决方案
- 1. callback回调函数
- 2. ES6 - Promise
- JavaScript高级程序设计(书)
- 在html中使用JavaScript
- script标签的位置
- 延迟脚本
- 异步脚本
- <noscript>元素
- 基本概念
- 严格模式
- 变量详解
- 数据类型
- typeof操作符
- undefined类型
- Null类型
- Boolean类型
- Number类型
- 深入了解ES6(书)
- var 、let 、 const
- 字符串与正则表达式
- 字符串
- 正则表达式
- 函数
- 函数形参默认值
- 使用不具名参数
- 函数构造器的增强能力
- 扩展运算符
- name属性
- 明确函数的多重用途
- 块级函数
- 箭头函数
- 尾调用优化
- 扩展的对象功能
- 对象类别
- 对象字面量语法的扩展
- ES6对象新增方法
- 重复的对象属性
- 自有属性的枚举顺序
- 更强大的原型
- 解构:更方便的数据访问
- 为什么要用解构?
- 对象解构
- 数组解构
- 混合解构
- 参数解构
- Symbol与Symbol属性
- 创建Symbol
- Symbol的使用方法
- Symbol全局私有属性
- Symbol与类型强制转换
- Symbol属性检索
- Symbol的一些构造方法
- Set集合与Map集合
- Set集合
- Weak Set集合(弱引用Set集合)
- Map集合
- JS标准内置对象
- Object 构造函数及属性
- Object 构造方法
- Symbol 内建对象类的函数及属性
- Set 构造函数及属性
- Weak Set 构造函数及属性
- JS杂项
- 类数组对象
- Class类的理解和使用