字符串的解耦赋值
字符串的解耦赋值被转换成了类似于数组的对象。
let [a,b,c,d,e] = 'Stark';
console.log(a) //S
console.log(b) //t
console.log(c) //a
console.log(d) //r
console.log(e) //k
数值与布尔值的解耦赋值
解耦赋值时,如果赋值运算符右边是数值或布尔值的话,则会先转换为对象。
let {toString:m} = 123
console.log(m === Number.prototype.toString); //true
let {toString:n} = true
console.log(n === Boolean.prototype.toString); //true
解耦赋值的规则是,只要赋值运算符右边的值不是对象或数组的话,会先转换为对象。由于undefined和null无法转换为对象,所以解耦赋值时会报错。
// TypeError:Cannot destructure property `prop` of 'undefined' of 'null'
let {prop:x} = undefined
let {prop:y} = null
函数参数的解耦赋值
声明函数时,函数的参数也可以使用解耦赋值。
function fn([a,b]){
console.log(a,b); // 1 2
}
fn([1,2])
小括号的问题
使用解耦赋值虽然很方便,但是解析并不容易。对于解析器来讲,语句中到底是模式还是表达式,没有办法从开始就知道,必须解析到运算符时才能知晓。
ECMAScript 6 的规则是只要有可能导致解耦赋值的歧义,就不得使用小括号。
但是,这条规则实际上不那么容易分辨,处理起来相当麻烦。因此,建议只要有可能就不要再模式中使用小括号。
不能使用小括号的情况
以下三种解耦赋值时不得使用小括号:
- 变量声明语句
//全部报错
let [(a)] = [1]
let {x:(c)} = {};
let ({x:c}) = {};
let {(x:c)} = {};
let {(x):c} = {};
let{o:({p:p})} = {o:{p:2}};
- 函数参数:函数参数也属于变量声明,因此不能带有小括号
//报错
function f([z]){return z;}
runction f([z.(x)]){return x;}
- 赋值语句的模式
//全部报错
({p:a}) = {p:42};
([a]) = [5];
解耦赋值的常见用途
交换变量之间的值
解耦赋值可用于两个变量之间交换值。
let x = 1;
let y = 2;
[x,y] = [y,x];
console.log(x,y); //2 1
从函数返回多个值
函数一般只能返回一个值。如果想要返回多个值,只能将多个值放置在数组或对象中。如果使用解耦赋值的话,很容易实现函数返回多个值。
// 返回一个数组
function example(){
return[1,2,3];
}
let [a,b,c] = example();
//返回一个对象
function example(){
return{
foo:1,
bar:2
}
}
let{foo,bar} = example();
函数参数的定义
解耦赋值可以很方便地将一组参数与变量名对应起来。
//参数是一组有次序的值
function f([x,y,z]){}
f([1,2,3])
//参数是一组无次序的值
function f({x,y,z}){}
f({z:3,y:2,x:1})
函数参数的默认值
例如jQuery提供的ajax()方法使用解耦赋值的默认值进行实现。
jQuery.ajax = function(url,{
async = true,
beforeSend = function(){},
cache = true,
complete = function (){}.
crossDomain = false,
global = true,
// ...more config
} = {}){
// ...do stuff
}
提取JSON数据
解耦赋值对于提取JSON对象中的数据内容尤其有用。
let jsonData = {
name:'Stark',
addr:'布鲁克林',
data:[444,909]
}
let{name,addr,data:number} = jsonData;
console.log(name,addr,number) // Stark 布鲁克林 [444,909]