变量的解构赋值
ES6允许我们通过数组或者对象的方式,对一组变量进行赋值,这就称为解构(等号两边的结构一定要相等这样才能拿到你需要的值)
字符串的解构赋值
JavaScript中字符串可以看成只读的数组,在字符串的结构赋值中有一个length属性可以获取该字符串长度
const [a, b, c, d, e] = 'hello';
// a = 'h', b = 'e'....
let {length : len} = 'hello'; // 该使用方法数组也合适
// len = 5
- 数组的解析是适合Set结构的和Iterator接口的
let [x, y, z] = new Set(['a', 'b', 'c']); // x = 'a', y = 'b', z = 'c'
回到顶部 目录
数组中的解构赋值
语法:let [a,b,c] = [1,2,3]
(把右边的值对应下表赋值给左边的变量)
本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值
let [a, [b, c], d] = [1, [2, 3], 4];
// a = 1, b = 2, c = 3, d = 4
let [e, , f] = [1, 2, 3];
// e = 1, f = 3
let [g, ...h] = [1, 2, 3, 4];
// g = 1, h = [2,3,4]
解析问题
-
如果变量对应没有值来解析,那么变量为
undefined
let [a] = []; // a = undefined let [b, c] = [1]; // b = 1, c = undefined let [d, [e], f] = [1, [2, 3], 4]; // d = 1, e = 2, f = 4
-
等号两边的类型不同,解析时会报错
// 报错 let [foo] = 1; let [foo] = false; let [foo] = NaN; let [foo] = undefined; let [foo] = null; let [foo] = {};
默认值
解构赋值:当变量存在默认值,如果该变量对应的值为undefined,那么变量就被赋予默认值,否则就为对应值
ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效
let [a = true] = [];
// a = true
let [x, y = 'b'] = ['a'];
// x='a', y='b'
let [x, y = 'b'] = ['a', undefined];
// x='a', y='b'
- 如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值
- 默认值可以引用解构赋值的其他变量,但该变量必须已经声明
function fn(){}
let [x = fn()] = [1];
let [x = 1, y = x] = [1, 2];
// x=1; y=2
let [x = y, y = 1] = [];
// ReferenceError: y is not defined
回到顶部 目录
对象的解构赋值
语法:let { a, b } = { a: 'aaa', b: 'bbb' };
(以变量与key对应赋值)
let obj = {
a: 'aa',
b: 'bb',
c: 'cc'
}
let [a, b, c] = obj;
解析问题
-
如果变量对应没有值来解析,那么变量为
undefined
let { c } = { a: 'aaa', b: 'bbb' }; // c = undefined
-
对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者
let { a: c } = { a: 'aaa', b: 'bbb' }; // c = "aaa" // a = error: a is not defined
就是把’aaa’的值赋值给c,a只是一个匹配模式,c才是真正的变量,这是针对这一种对象的解构赋值
-
如果要将一个已经声明的变量用于解构赋值
// 错误的写法 let x; {x} = {x: 1}; // SyntaxError: syntax error // 正确的写法 let x; ({x} = {x: 1});
由于let x;该语句以及结束,js解释器就会把{x}解析成代码块
默认值
var {x = 3} = {};
// x = 3
var {x = 3} = {x: undefined};
// x = 3
var {x = 3} = {x: null};
// x = null
属性的简写
- ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法
- 简写的对象方法不能用作构造函数,会报错
// 1.属性简写 function fn(x, y){ return{ x: x, y: y } } // ==> function fn(x,y){ return {x,y}; } // 2.方法简写 const obj1 = { fn : function(){ return 0; } } // ==> const obj2 = { fn(){ return 0; } } // 3.常用实例 let ms = {}; function getItem (key) { return key in ms ? ms[key] : null; } function setItem (key, value) { ms[key] = value; } function clear () { ms = {}; } const exports1 = { getItem: getItem, setItem: setItem, clear: clear }; // ==> const exports2 = { getItem, setItem, clear }; // 4.简写的对象方法不能用作构造函数,会报错 const obj3 = { f() { this.foo = 'bar'; } }; new obj3.f() // 报错
属性表达式
JavaScript定义属性的方式,在ES6之前只有一种方法
- 直接用标识符作为属性名称(ES6以前)
- 表达式作为属性名称(表示放在[]里面,新增加的一种方法)
// 1. 用于属性 let a = 'he'; const obj1 = { [a] : true, ['a' + 'b']: 2 } console.log(obj1[a]) // true console.log(obj1.ab) // 2 console.log(obj1['ab']) // 2 // 2. 用于方法名称 const obj2 = { ['h'+'e'](){ return '2'; } } obj2.he() //"2" // 3. 注意属性名不能为对象 const keyA = {a: 1}; const keyB = {b: 2}; const myObject = { [keyA]: 'valueA', [keyB]: 'valueB' }; myObject // Object {[object Object]: "valueB"} // [keyA]和[keyB]得到的都是[object Object],所以[keyB]会把[keyA]覆盖掉,而myObject最后只有一个[object Object]属性,这就是","的操作
- 属性名表达式与简洁表示法,不能同时使用,会报错
const baz = { [foo] };
- 属性名表达式如果是一个对象,默认情况下会自动将对象转为字符串[object Object]
- 属性名表达式与简洁表示法,不能同时使用,会报错
回到顶部 目录
函数参数的解构赋值
语法:[[1, 2], [3, 4]].map(([a, b]) => a + b); \\ [3, 7]
function fn({
a,
b,
c = 10,
d = 20,
} = {}){
return a+b+c+d;
}
fn({a:1,b:2})
// 33
语法都是上面数组和对象的解构赋值
圆括号问题
尽量不要写带有()的语句出来
解构赋值虽然很方便,但是解析起来并不容易。对于编译器来说,一个式子到底是模式,还是表达式,没有办法从一开始就知道,必须解析到(或解析不到)等号才能知道,乱加圆括号也是导致编译报错
不能使用圆括号的情况:
- 变量声明语句
let [(a)] = [1]
- 函数参数
function fn([(z)]){}
- 赋值语句的模式
[({ p: a }), { x: c }] = [{}, {}];
可以使用圆括号的情况:
[(b)] = [3];
({ p: (d) } = {});
[(parseInt.prop)] = [3];
用途
- 交换变量的值
[a, b] = [b, a]
- 从函数返回多个值、提取json数据
函数的返回值是一个对象的时候,我们可以用解构赋值来接受 - 函数参数的定义、函数参数的默认值(上面的函数参数的解构赋值)
- 其实就是来方便我们编写代码的
回到顶部 目录