文章目录
什么是JavaScript的解构?
哲学家们还没给出确切的定义,所以我就用我自己理解的来了。这个是解构: 按照德里达的解释,解构不是理论,不是方法,更不是概念!!!解构,它仅仅是一种策略,是一种实践活动,其目的在于颠覆传统西方理论和各种方法论,同样也颠覆一切靠语言规则建构起来的逻辑体系。德里达称解构不能受困于语言规则和逻辑体系,重在显示它的自我创造精神。
以下都是个!人!理!解!
解构是将一个大的复杂的东西分解并重构成多个易于理解的小的东西。这个东西可以是一个概念也可以是一个实体。
JavaScript的解构是分解结构,并对应赋值的过程。将一个对象分解成多个小的对象。
模式匹配的解构
只要等号左值和右值的模式相同便可一一对应赋值。
//数组
var [a,b,c] = [1,2,3];
console.log(a,b,c);
//Output: 1 2 3
var [a, [b], c] = [1,[2,3],4];
console.log(a,b,c);
//Output 1 2 4
var [a, b, c] = [1,[2,3],4];
console.log(a,b,c);
//Output 1 [2,3] 4
var [a,b,c] = new Set([1,2,3]);
console.log(a,b,c);
//Output: 1 2 3
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();
console.log(first,second,third,fourth,fifth,sixth);
//Output:0 1 1 2 3 5
解构不成功
部分对应的变量值是undefined。简单点说是左值模式中的待赋值个数大于右值模式中的值个数,导致部分变量无值而undefined。
var [a] = [];
var [a,b] = [1];
console.log(a,b);
//Output: 1 undefined
不完全解构
左值模式中的待赋值变量个数少于右值模式中的值个数,只匹配一部分。
let [a,b] = [1,2,3];
console.log(a,b);
//Output: 1 2
非对象解构
如果右值不是对象,那么将其转为对象后判断是否具备Iterator接口。
// 以下都是报错的例子
let [a] = 1; //Output:1 is not iterable
let [b] = false; //Output:false is not iterable
let [c] = NaN; //Output:NaN is not iterable
let [e] = undefined; //Output:undefined is not iterable
let [f] = null; //Output:null is not iterable
let [g] = {}; //Output:{} is not iterable
默认值
允许指定默认值,只有严格===undefined,默认值才会生效。
当默认值为函数时,只有当赋值为undefined的时候,函数才会执行。
可以引用解构赋值过程中的其他变量,但是这个变量必须先行声明。
//普通
var {x = 3} = {};
var {x : y = 1} = {};
console.log(x,y);
//Output: 3 1
//函数参数
function func({a = 0,b = 0} = {}){
console.log(a,b);
}
func();
//Output: 0 0
func({a:3,b:3});
//Output: 3 3
//函数参数2
var arr = [1,2,undefined,4];
var arr2 = arr.map((x = 0) => x);
console.log(arr2);
//Output: [1,2,0,4]
已声明的变量进行解构赋值
如果直接写
var x;
{x} = {x:1};
//Output: Uncaught SyntaxError: Unexpected token =
正确的完整写法,在解构赋值语句上加上圆括号。以避免JavaScript将{x}识别为代码块。
var x;
({x} = {x:1});
console.log(x);
//Output: 1
各类型数据的解构赋值
对象
对象解构时,变量必须与属性名同名,才能取到正确的值。
var {a,b,c} = {a:1,b:2,d:3};
console.log(a, b,c);
//Output:1 2 undefined
如果变量名与属性名不一致,则必须在左值处使用同属性名为属性名,待赋值变量为值的形式进行赋值,否则取不到值。如下所示
var obj = {a:1};
var {b} = obj;
var {a: val} = obj;
console.log(val, b);
//Output: 1 undefined
字符串
字符串会被转为一个字符数组,然后再进行解构赋值。
let [a,b,c,d,e] = "Hello";
console.log(a,b,c,d,e):
//Output: H e l l o
还拥有length属性
let {length} = "hello";
console.log(length);
//Output: 5
数值和布尔值
若右值为数值或布尔值,那么会将其先转为对象。然后从原型对象中找到对应的属性。不过null与undefined无法转为对象,所以进行解构赋值都会报错。
let {toString : s1} = 123;
let {toString : s2} = true;
console.log(s1,s2);
//Output:ƒ toString() { [native code] } ƒ toString() { [native code] }
s1 === Number.prototype.toString
//Output: true
s2 === Boolean.prototype.toString
//Output: true
函数参数
传入参数的时候,可以进行解构赋值。
function add([a,b]){
return a + b;
}
var r = add([1,2]);
console.log(r);
//Output: 3
var arr = [[1,2],[3,4]];
arr.map(([a,b]) => a + b)
参数在传入的过程中先执行了
([a,b] = [1,2]);
进行解构赋值。
解构赋值过程中的圆括号
解构赋值对于编译器,必须解析到等号才能知道是模式,否则是表达式。所以规定只要有可能导致解构的歧义,就不得使用圆括号。
不能
- 声明变量语句中
- 函数参数的模式中。因为函数参数相当于在声明变量。
- 赋值语句中,不能将整个模式或嵌套模式中的一层,放在圆括号之内。
//1)
var [(a)] = {}var [(a)] = [1];
var {x: (c)} = {};
var ({x: c}) = {};
var {(x: c)} = {};
var {(x): c} = {};
var { o: ({ p: p }) } = { o: { p: 2 } };
//2)
function f([(z)]) { return z; }
//3)
({ p: a }) = { p: 42 };
([a]) = [5];
[({ p: a }), { x: c }] = [{}, {}];
能
赋值语句的非模式部分
用途
- 交换变量的值
var x = 1,y = 2;
([x,y] = [y,x])
- 从函数返回多个值
- 定义函数参数
- 提取JSON数据
- 函数参数的默认值
- 遍历map结构
var map = new Map();
map.set('first', 'hello');
map.set('second', 'world');
for (let [key, value] of map) {
console.log(key + " is " + value);
}
/*Output:
first is hello
second is world
*/
- 输入模块的指定方法
const {module1, module2} = require("source");
整理及概念参考来源:
http://caibaojian.com/es6/destructuring.html
https://www.douban.com/group/topic/11258053/
(PS:感觉哲学层面的解构就是杠精思想。)