变量解构与赋值
基本用法
ES6允许按照一定的模式,从数组和对象中提取值,对变量进行赋值。写法如下:
| let [a, b, c] = [1, 2, 3]; a b c
var a = 1; var b = 2; var c = 3;
|
本质上只有等号两边的模式匹配的情况下,解构变量才会成功,如果解构不成功,那么值就等于undefined;但是即便两边的模式不完全匹配也是可以解构成功的。即:等号右边的模式仅等于等号左边声明的一部分。例如:
1 2 3
| let [x, y] = [1, 2, 3]; x y
|
适用范围
除了var
变量可以解构赋值,还有let
和const
也可以解构,除此之外,一种数据结构只要其有Iterator接口都可以使用数组解构赋值。例如:
1 2 3 4 5 6 7 8 9
| let [a, b, c] = new Set({'aa', 'bb', 'cc'}); a b c
const [d, e, f] = new Set({'dd', 'ee', 'ff'}); d e f
|
使用Generator函数解斐波那契数列,内部使用解构赋值,每次循环过程中变量a
和b
都会重新赋值;
1 2 3 4 5 6 7 8 9 10 11
| function* fibs() { var a = 0; var b = 1; while(true) { yield a; [a, b] = [b, a + b]; } }
var [first, second, third, fourth, fifth, sixth] = fibs(); sixth
|
初始化
变量解构可以在声明前初始化,注意:如果解构右侧值不等于undefined
那么初始化的值就不会生效。例如:
1 2 3 4 5
| let [x, y = 'y'] = [x, undefined]; y
let [x, y = 'y'] = [x, null]; y
|
如果解构默认值是一个表达式,那么只有在需要使用到表达式的时候才会赋值,否则默认值无效。
1 2 3 4 5 6 7
| function f() { console.log('aaa'); }
let [x = f()] = [1]; x
|
对象的解构
除了可以对数组做解构,对象同样可以做解构,但是与数组有区别的是:对象解构只有在对象属性名相同的情况下才能解构成功,如下:
1 2 3 4 5 6
| let {foo, bar} = {foo: 'aaa', bar: 'bbb'} foo bar
let {baz} = {foo: 'aaa', bar: 'bbb'} baz
|
如果变量名和属性名不一样必须写成下面这样才行;
1 2 3 4 5 6 7
| var {foo: baz} = {foo: 'aaa', bar: 'bbb'} baz
let object = {first: 'hello', last: 'world'}; let {first: f, last: l} = object; f l
|
解构也可以用于嵌套结构的对象
1 2 3 4 5 6 7 8 9 10 11
| var obj = { p: [ 'Hello', {y: 'world'} ] };
var {p: [x, {y}]} = obj; x y
|
解构已声明的变量
如果需要给已经声明的变量解构,一定要使用圆括号将其包裹起来,否则JavaScript引擎会将其解析为代码块。从而导致解构失败。ES6在解构变量时,除非会造成歧义必须使用圆括号围起来,否则不推荐使用圆括号;
1 2 3 4 5 6 7 8 9 10
| var x; {x} = {x: 1}
var x; ({x} = {x: 1})
let {log, sin, cos} = Math;
|
字符串的解构
字符串也可以解构,解构出来的结果是当作数组处理。程序代码如下:
1 2 3 4 5 6 7 8 9 10
| const [a, b, c, d, e] = 'hello'; a b c d e
let {length: len} = 'hello'; len
|
数值和布尔值的解构赋值
解构赋值时,如果等号右边是数值和布尔值,则会先转换为对象;但是undefined
和null
无法转为对象,因此会解构失败;
1 2 3 4 5
| let {toString: s} = 123; s === Number.prototype.toString
let {toString: s} = true; s === Boolean.prototype.toString
|
函数参数的解构赋值
函数参数也可以解构赋值
1 2 3 4 5 6 7 8
| function add([x, y]) { return x + y; }
add([1, 2]);
[[1, 2], [3, 4]].map(([a, b]) => a + b);
|
函数参数的解构也可以使用默认值(这不是废话嘛)
1 2 3 4 5 6 7 8
| function move({x = 0, y = 0} = {}) { return [x, y]; }
move({x: 3, y: 8}); move({x: 3}); move({}); move();
|
下面这种写法不是解构,而是给函数参数设置默认值
1 2 3 4 5 6 7 8
| function move({x, y} = {x: 0, y: 0}) { return [x, y]; }
move({x: 3, y: 8}); move({x: 3}); move({}); move();
|
说了那么多,解构有什么用呢?
交换变量的值
从函数返回多个值
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function example() { return [1, 2, 3]; }
var [a, b, c] = example();
function example() { return { foo: 1, bar: }; } var {foo, bar} = example();
|
函数参数的定义
1 2
| function f([x, y, z]) { ... } f([1, 2, 3]);
|
提取JSON数据
1 2 3 4 5 6 7 8 9 10
| var jsonData = { id: 42, status: "OK", data: [867, 5309] };
let {id, status, data: number} = jsonData;
console.log(id, status, number);
|
函数参数的默认值
1 2 3 4 5 6 7 8 9 10 11
| jQuery.ajax = function (url, { async = true, beforeSend = function() {}, cache = true, complete = function() {}, crossDomain = false, global = true, // ... more config params }) { };
|
遍历Map解构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| var map = new Map(); map.set('first', 'hello'); map.set('last', 'world');
for (let [key, value] of map) { console.log(key + " is " + value); }
for (let [key] of map) { }
for (let [,value] of map) { }
|
输入模块的指定方法
1 2 3 4
| const { SourceMapConsumer, SourceNode } = require("source-map");
import { SourceMapConsumer, SourceNode } from 'source-map';
|