解构赋值

*非常有用,尤其是数据交互的时候,例如ajax

let [a,b,c] = [3,4,5]
即可以对abc记性赋值。

当进行json解析时,可以使用解构赋值的方式。

let{name,age,job} = { name:‘strike’,age:18,job:‘programming’ }

解构赋值的时候,也可以进行别名的设置。

赋值默认值
let [a,b,c=5] = [3,4]

也可以进行 值互换
[a,b] = [b,a]

import解构
import [a,b,c] from ‘./mod’

数组的结构赋值

基本用法

	// 传统的为变量赋值的方式
	let a = 1;
	let b = 2;
	let c = 3;
	// ES6中的解构赋值
	let [a, b, c] = [1, 2, 3];

上面的代码表示,可以从数组中提取质,按照对应位置,对变量赋值。

本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,坐标的变量就会被赋予对应的值。下面试一些使用嵌套数组进行解构的例子。

	let [foo, [[bar], baz]] = [1, [[2], 3]];
	foo // 1
	bar // 2
	baz // 3
	
	let [ , , third] = ["foo", "bar", "baz"];
	third // "baz"
	let [x, , y] = [1, 2, 3];
	x // 1
	y // 3
	
	let [head, ...tail] = [1, 2, 3, 4];
	head // 1
	tail // [2, 3, 4]
	
	// 注意这里z解构的结果
	let [x, y, ...z] = ['a'];
	x // "a"
	y // undefined
	z // []

如果解构不成功,变量的值就等于undefined。

另一种情况是不完全解构,即等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功。

	let [x, y] = [1, 2, 3];
	x // 1
	y // 2
	
	let [a, [b], d] = [1, [2, 3], 4];
	a // 1
	b // 2
	d // 4

默认值

解构赋值允许使用默认值。

	let [foo = true] = [];
	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];
	x // 1
	let [x = 1] = [null];
	x // null

上面代码中,如果一个数组成员是 null ,默认值就不会生效,因为 null 不严格等于 undefined 。

如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值。

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

	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 还没有声明。

对象的解构赋值

解构不仅可以用于数组,还可以用于对象。不过,对于对象的结构,变量必须与属性同名。

	let { foo, bar } = { foo: "aaa", bar: "bbb" };
	foo // "aaa"
	bar // "bbb"

实际上,对象的上述的完整形式如下

	// 冒号前面的是模式,后面的是变量
	let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };

如果变量与属性不同名,可以使用这种方式进行解构

	let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
	baz // "aaa"
	let obj = { first: 'hello', last: 'world' };
	let { first: f, last: l } = obj;
	f // 'hello'
	l // 'world'

与数组一样,解构也可以用于嵌套结构的对象。

	let obj = {
	 p: [
	 'Hello',
	 { y: 'World' }
	 ]
	};
	let { p: [x, { y }] } = obj;
	x // "Hello"
	y // "World"

注意,**这时 p 是模式,不是变量,因此不会被赋值。**如果 p 也要作为变量赋值,可以写成下面这样。

	let obj = {
	 p: [
	 'Hello',
	 { y: 'World' }
	 ]
	};
	let { p, p: [x, { y }] } = obj;
	x // "Hello"
	y // "World"
	p // ["Hello", {y: "World"}]

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

	var {x = 3} = {};
	x // 3
	var {x, y = 5} = {x: 1};
	x // 1
	y // 5
	var {x: y = 3} = {};
	y // 3
	var {x: y = 3} = {x: 5};
	y // 5
	var { message: msg = 'Something went wrong' } = {};
	msg // "Something went wrong"

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

// 报错
let {foo: {bar}} = {baz: 'baz'};

上面代码中,等号左边对象的 foo 属性,对应一个子对象。该子对象的 bar 属性,解构时会报错。原因很简单,因为 foo 这时等于 undefined ,再取子属
性就会报错,请看下面的代码。
let _tmp = {baz: ‘baz’};
_tmp.foo.bar // 报错
如果要将一个已经声明的变量用于解构赋值,必须非常小心。

	// 错误的写法
	let x;
	{x} = {x: 1};
	// SyntaxError: syntax error

上面代码的写法会报错,因为 JavaScript 引擎会将 {x} 理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。

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

上面代码将整个解构赋值语句,放在一个圆括号里面,就可以正确执行。关于圆括号与解构赋值的关系,参见下文。
解构赋值允许等号左边的模式之中,不放置任何变量名。因此,可以写出非常古怪的赋值表达式。

({} = [true, false]);
({} = 'abc');
({} = []);

上一章 下一章
上面的表达式虽然毫无意义,但是语法是合法的,可以执行。
对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量。

let { log, sin, cos } = Math;

上面代码将 Math 对象的对数、正弦、余弦三个方法,赋值到对应的变量上,使用起来就会方便很多。
由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。

let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3

上面代码对数组进行对象解构。

圆括号问题

解构赋值虽然很方便,但是解析起来并不容易。对于编译器来说,一个式子到底是模式,还是表达式,没有办法从一开始就知道,必须解析到(或解析不
到)等号才能知道。
由此带来的问题是,如果模式中出现圆括号怎么处理。ES6 的规则是,只要有可能导致解构的歧义,就不得使用圆括号。
但是,这条规则实际上不那么容易辨别,处理起来相当麻烦。因此,建议只要有可能,就不要在模式中放置圆括号。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值