第3章 变量的解构赋值
作者:互联网
3.1 数组的解构赋值
3.1.1 基本用法
ES6 允许按照一定模式从数组和对象中提取值,然后对变量进行赋值,这被称为解构(Destructuring)。
以前,为变量赋值只能直接指定值。
// hzh.js
let hzh1 = 1;
let hzh2 = 2;
let hzh3 = 3;
ES6允许写成下面这样。
// hzh.js
let [hzh1, hzh2, hzh3] = [1, 2, 3];
上面的代码表示,可以从数组中提取值,按照对应位置对变量赋值。
本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。下面是一些使用嵌套数组进行解构的例子。
// hzh.js
let [hzh1, [[hzh2], hzh3]] =[ 1,[[2], 3] ];
console.log("hzh1 = " + hzh1);
console.log("hzh2 = "+ hzh2);
console.log("hzh3 = " + hzh3);
[Running] node "e:\HMV\Babel\hzh.js"
hzh1 = 1
hzh2 = 2
hzh3 = 3
[Done] exited with code=0 in 0.173 seconds
// hzh.js
let [ , , third ,] = ["尤雨溪", "人世间", "黄子涵"];
console.log("third = " + third);
[Running] node "e:\HMV\Babel\hzh.js"
third = 黄子涵
[Done] exited with code=0 in 0.83 seconds
// hzh.js
let [hzh1, , hzh3] = [1, 2, 3];
console.log("hzh1 = " + hzh1);
console.log("hzh3 = " + hzh3);
[Running] node "e:\HMV\Babel\hzh.js"
hzh1 = 1
hzh3 = 3
[Done] exited with code=0 in 0.205 seconds
// hzh.js
let [hzh1, ...hzh2] = [1, 2, 3, 4];
console.log("输出hzh1的值:");
console.log(hzh1);
console.log("输出hzh2的值:");
console.log(hzh2);
[Running] node "e:\HMV\Babel\hzh.js"
输出hzh1的值:
1
输出hzh2的值:
[ 2, 3, 4 ]
[Done] exited with code=0 in 0.179 seconds
// hzh.js
let [hzh1, hzh2, ...hzh3] = ['黄子涵'];
console.log("输出hzh1的值:");
console.log(hzh1);
console.log("输出hzh2的值:");
console.log(hzh2);
console.log("输出hzh3的值:");
console.log(hzh3);
[Running] node "e:\HMV\Babel\hzh.js"
输出hzh1的值:
黄子涵
输出hzh2的值:
undefined
输出hzh3的值:
[]
[Done] exited with code=0 in 0.201 seconds
如果解构不成功,变量的值就等于undefined。
// hzh.js
let [hzh1] = [];
let [hzh2, hzh3] = [1];
console.log("hzh1 = "+ hzh1);
console.log("hzh2 = "+ hzh2);
console.log("hzh3 = "+ hzh3);
[Running] node "e:\HMV\Babel\hzh.js"
hzh1 = undefined
hzh2 = 1
hzh3 = undefined
[Done] exited with code=0 in 0.198 seconds
以上两种情况都属于解构不成功,hzh和hzh3的值都会等于undefined。
另一种情况是不完全解构,即等号左边的模式只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功。
// hzh.js
let [hzh1, hzh2] = [1, 2, 3];
let [hzh3, [hzh4], hzh5] = [3, [4, '不解构'], 5];
console.log("hzh1 = "+ hzh1);
console.log("hzh2 = "+ hzh2);
console.log("hzh3 = "+ hzh3);
console.log("hzh4 = "+ hzh4);
console.log("hzh5 = "+ hzh5);
[Running] node "e:\HMV\Babel\hzh.js"
hzh1 = 1
hzh2 = 2
hzh3 = 3
hzh4 = 4
hzh5 = 5
[Done] exited with code=0 in 0.226 seconds
上面两个例子都属于不完全解构,但是可以成功。
如果等号的右边不是数组(或者严格来说不是可遍历的结构),那么将会报错。
// hzh.js
// 报错的例子
let [hzh1] = 1;
console.log(hzh1);
[Running] node "e:\HMV\Babel\hzh.js"
e:\HMV\Babel\hzh.js:4
let [hzh1] = 1;
^
TypeError: 1 is not iterable
at Object.<anonymous> (e:\HMV\Babel\hzh.js:4:14)
at Module._compile (internal/modules/cjs/loader.js:999:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
at Module.load (internal/modules/cjs/loader.js:863:32)
at Function.Module._load (internal/modules/cjs/loader.js:708:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
at internal/main/run_main_module.js:17:47
[Done] exited with code=1 in 0.168 seconds
// hzh.js
// 报错的例子
let [hzh2] = false;
console.log(hzh2);
[Running] node "e:\HMV\Babel\hzh.js"
e:\HMV\Babel\hzh.js:4
let [hzh2] = false;
^
TypeError: false is not iterable
at Object.<anonymous> (e:\HMV\Babel\hzh.js:4:14)
at Module._compile (internal/modules/cjs/loader.js:999:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
at Module.load (internal/modules/cjs/loader.js:863:32)
at Function.Module._load (internal/modules/cjs/loader.js:708:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
at internal/main/run_main_module.js:17:47
[Done] exited with code=1 in 0.169 seconds
// hzh.js
// 报错的例子
let [hzh3] = NaN;
console.log(hzh3);
[Running] node "e:\HMV\Babel\hzh.js"
e:\HMV\Babel\hzh.js:4
let [hzh3] = NaN;
^
TypeError: NaN is not iterable
at Object.<anonymous> (e:\HMV\Babel\hzh.js:4:14)
at Module._compile (internal/modules/cjs/loader.js:999:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
at Module.load (internal/modules/cjs/loader.js:863:32)
at Function.Module._load (internal/modules/cjs/loader.js:708:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
at internal/main/run_main_module.js:17:47
[Done] exited with code=1 in 0.194 seconds
// hzh.js
// 报错的例子
let [hzh4] = undefined;
console.log(hzh4);
[Running] node "e:\HMV\Babel\hzh.js"
e:\HMV\Babel\hzh.js:4
let [hzh4] = undefined;
^
TypeError: undefined is not iterable
at Object.<anonymous> (e:\HMV\Babel\hzh.js:4:14)
at Module._compile (internal/modules/cjs/loader.js:999:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
at Module.load (internal/modules/cjs/loader.js:863:32)
at Function.Module._load (internal/modules/cjs/loader.js:708:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
at internal/main/run_main_module.js:17:47
[Done] exited with code=1 in 0.186 seconds
// hzh.js
// 报错的例子
let [hzh5] = null;
console.log(hzh5);
[Running] node "e:\HMV\Babel\tempCodeRunnerFile.js"
e:\HMV\Babel\tempCodeRunnerFile.js:4
let [hzh5] = null;
^
TypeError: null is not iterable
at Object.<anonymous> (e:\HMV\Babel\tempCodeRunnerFile.js:4:14)
at Module._compile (internal/modules/cjs/loader.js:999:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
at Module.load (internal/modules/cjs/loader.js:863:32)
at Function.Module._load (internal/modules/cjs/loader.js:708:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
at internal/main/run_main_module.js:17:47
[Done] exited with code=1 in 0.169 seconds
// hzh.js
// 报错的例子
let [hzh6] = {};
console.log(hzh6);
[Running] node "e:\HMV\Babel\hzh.js"
e:\HMV\Babel\hzh.js:4
let [hzh6] = {};
^
TypeError: {} is not iterable
at Object.<anonymous> (e:\HMV\Babel\hzh.js:4:14)
at Module._compile (internal/modules/cjs/loader.js:999:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
at Module.load (internal/modules/cjs/loader.js:863:32)
at Function.Module._load (internal/modules/cjs/loader.js:708:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
at internal/main/run_main_module.js:17:47
[Done] exited with code=1 in 0.17 seconds
上面的语句都会报错,因为等号右边的值或是转为对象以后不具备 Iterator 接口(前五个表达式),或是本身就不具备 Iterator 接口(最后一个表达式)。
对于 Set 结构,也可以使用数组的解构赋值。
// hzh.js
let [hzh1, hzh2, hzh3] = new Set(['黄子涵', '尤雨溪', '人世间']);
console.log("hzh1 = " + hzh1);
[Running] node "e:\HMV\Babel\hzh.js"
hzh1 = 黄子涵
[Done] exited with code=0 in 0.506 seconds
事实上,只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值。
// hzh.js
function* fibs() {
let hzh1 = 1;
let hzh2 = 2;
while(true) {
yield hzh1;
[hzh1, hzh2] = [hzh2, hzh1 + hzh2];
}
}
let [first, second, third, fourth, fifth, sixth] = fibs();
console.log(sixth);
[Running] node "e:\HMV\Babel\hzh.js"
13
[Done] exited with code=0 in 0.176 seconds
上面的代码中,fibs 是一个 Generator 函数,原生具有 Iterator 接口。解构赋值会依次从这个接口中获取值。
上面关于fibs函数这部分不是很懂。
3.1.2 默认值
// hzh.js
let [hzh1 = true] = [];
console.log("hzh1 = " + hzh1);
[Running] node "e:\HMV\Babel\hzh.js"
hzh1 = true
[Done] exited with code=0 in 0.194 seconds
// hzh.js
let [hzh2, hzh3 = 'b'] = ['黄子涵是帅哥!'];
let [hzh4, hzh5 = 'c'] = ['黄子涵是靓仔!', undefined];
console.log("hzh2 = " + hzh2);
console.log("hzh3 = " + hzh3);
console.log("hzh4 = " + hzh4);
console.log("hzh5 = " + hzh5);
[Running] node "e:\HMV\Babel\hzh.js"
hzh2 = 黄子涵是帅哥!
hzh3 = b
hzh4 = 黄子涵是靓仔!
hzh5 = c
[Done] exited with code=0 in 0.192 seconds
注意
ES6 内部使用严格相等运算符(===)判断一个位置是否有值。所以,如果一个数组成员不严格等于undefined,默认值是不会生效。
// hzh.js
let [hzh1 = 1] = [undefined];
let [hzh2 = 2] = [null];
console.log("hzh1 = " + hzh1);
console.log("hzh2 = " + hzh2);
[Running] node "e:\HMV\Babel\hzh.js"
hzh1 = 1
hzh2 = null
[Done] exited with code=0 in 0.576 seconds
上面的代码,如果一个数组成员,默认值就不会生效,因为 null 不严格相等 undefined。
如果默认值是一个表达式,那么这个表达式是惰性求值,即只有在用到时才会求值。
// hzh.js
function huangzihan() {
console.log('黄子涵');
}
let [hzh = huangzihan()] = [1];
[Running] node "e:\HMV\Babel\hzh.js"
[Done] exited with code=0 in 0.594 seconds
上面的代码中,因为 x 能取到值,所以函数 f 根本不会执行。上面的代码其实等价于下面的代码。
// hzh.js
let hzh;
if([1][0] === undefined) {
hzh = huangzihan();
} else {
hzh = [1][0];
}
[Running] node "e:\HMV\Babel\tempCodeRunnerFile.js"
[Done] exited with code=0 in 0.194 seconds
默认值可以引用解构赋值的其他变量,但该变量必须已经声明。
// hzh.js
let [hzh1 = 1, hzh2 = hzh1] = [];
console.log("hzh1 = " + hzh1);
console.log("hzh2 = " + hzh2);
[Running] node "e:\HMV\Babel\hzh.js"
hzh1 = 1
hzh2 = 1
[Done] exited with code=0 in 0.176 seconds
// hzh.js
let [hzh3 = 3, hzh4 = hzh3] = [2];
console.log("hzh3 = " + hzh3);
console.log("hzh4 = " + hzh4);
[Running] node "e:\HMV\Babel\hzh.js"
hzh3 = 2
hzh4 = 2
[Done] exited with code=0 in 0.196 seconds
// hzh.js
let [hzh5 = 5, hzh6 = hzh5] = [1, 2];
console.log("hzh5 = " + hzh5);
console.log("hzh6 = " + hzh6);
[Running] node "e:\HMV\Babel\hzh.js"
hzh5 = 1
hzh6 = 2
[Done] exited with code=0 in 0.179 seconds
// hzh.js
let [hzh7 = hzh8, hzh8 = 8] = [];
console.log("hzh7 = " + hzh7);
console.log("hzh8 = " + hzh8);
[Running] node "e:\HMV\Babel\tempCodeRunnerFile.js"
e:\HMV\Babel\tempCodeRunnerFile.js:3
let [hzh7 = hzh8, hzh8 = 8] = [];
^
ReferenceError: Cannot access 'hzh8' before initialization
at Object.<anonymous> (e:\HMV\Babel\tempCodeRunnerFile.js:3:13)
at Module._compile (internal/modules/cjs/loader.js:999:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
at Module.load (internal/modules/cjs/loader.js:863:32)
at Function.Module._load (internal/modules/cjs/loader.js:708:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
at internal/main/run_main_module.js:17:47
[Done] exited with code=1 in 0.23 seconds
上面最后一个表达式之所以会报错,是因为 hzh7 用到默认值 hzh8 时,hzh8 还没有声明。
3.2 对象的解构赋值
解构不仅可以用于数组,还可以用于对象。
// hzh.js
let { hzh1, hzh2 } = { hzh1: "黄子涵", hzh2: "尤雨溪" };
console.log("hzh1 = " + hzh1);
console.log("hzh2 = " + hzh2);
[Running] node "e:\HMV\Babel\hzh.js"
hzh1 = 黄子涵
hzh2 = 尤雨溪
[Done] exited with code=0 in 0.229 seconds
对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值是由它的位置决定的;而对象的属性没有次序,变量必须与属性同名才能取到正确的值。
// hzh.js
let { hzh2, hzh1 } = { hzh1: "黄子涵", hzh2: "尤雨溪" };
console.log("hzh1 = " + hzh1);
console.log("hzh2 = " + hzh2);
[Running] node "e:\HMV\Babel\hzh.js"
hzh1 = 黄子涵
hzh2 = 尤雨溪
[Done] exited with code=0 in 0.196 seconds
// hzh.js
let { hzh2 } = { hzh1: "黄子涵", hzh2: "尤雨溪" };
console.log("hzh3 = " + hzh3);
[Running] node "e:\HMV\Babel\hzh.js"
e:\HMV\Babel\hzh.js:4
console.log("hzh3 = " + hzh3);
^
ReferenceError: hzh3 is not defined
at Object.<anonymous> (e:\HMV\Babel\hzh.js:4:25)
at Module._compile (internal/modules/cjs/loader.js:999:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
at Module.load (internal/modules/cjs/loader.js:863:32)
at Function.Module._load (internal/modules/cjs/loader.js:708:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
at internal/main/run_main_module.js:17:47
[Done] exited with code=1 in 0.171 seconds
上面代码的第一个例子中,等号左边的两个变量的次序与等号右边两个同名属性的次序不一致,但是对取值完全没有影响。第二个例子的变量没有对应的同名属性,导致取不到值,最后等于 undefined 。
如果变量名与属性名不一致,必须写成下面这样
// hzh.js
let { hzh1: hzh3 } = { hzh1: "黄子涵", hzh2: "尤雨溪" };
console.log("hzh3 = " + hzh3);
[Running] node "e:\HMV\Babel\hzh.js"
hzh3 = 黄子涵
[Done] exited with code=0 in 0.203 seconds
// hzh.js
let huangzihan = { hzh1: '黄子涵', hzh2: '尤雨溪'};
let { hzh1: h, hzh2: z} = huangzihan;
console.log("hzh1对象的h属性:" + h);
console.log("hzh2对象的z属性:" + z);
[Running] node "e:\HMV\Babel\hzh.js"
hzh1对象的h属性:黄子涵
hzh2对象的z属性:尤雨溪
[Done] exited with code=0 in 0.194 seconds
实际上说明,对象的解构赋值是下面形式的简写。
// hzh.js
let { hzh1: hzh1, hzh2: hzh2} = { hzh1: '黄子涵', hzh2: '尤雨溪'};
console.log("hzh1 = " + hzh1);
console.log("hzh2 = " + hzh2);
[Running] node "e:\HMV\Babel\hzh.js"
hzh1 = 黄子涵
hzh2 = 尤雨溪
[Done] exited with code=0 in 0.2 seconds
也就是说,对象的解构赋值的内部机制是先找到同名属性,然后再赋值给对应的变量。真正被赋值的是后者,而不是前者。
// hzh.js
let { hzh1: hzh3} = { hzh1: '黄子涵', hzh2: '尤雨溪'};
console.log("hzh3 = " + hzh3);
console.log("hzh1 = " + hzh1);
[Running] node "e:\HMV\Babel\hzh.js"
hzh3 = 黄子涵
e:\HMV\Babel\hzh.js:5
console.log("hzh1 = " + hzh1);
^
ReferenceError: hzh1 is not defined
at Object.<anonymous> (e:\HMV\Babel\hzh.js:5:25)
at Module._compile (internal/modules/cjs/loader.js:999:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
at Module.load (internal/modules/cjs/loader.js:863:32)
at Function.Module._load (internal/modules/cjs/loader.js:708:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
at internal/main/run_main_module.js:17:47
[Done] exited with code=1 in 0.176 seconds
上面的代码中,hzh1是匹配的模式,hzh3才是变量。真正被赋值的是变量 hzh3,而不是模式 hzh1。
与数组一样,解构也可以用于嵌套结构的对象。
注意,这时p是模式,不是变量,因此不会被赋值。如果p也要作为变量赋值,可以写成下面这样。
上面的代码有三次解构赋值,分别是对 loc、start、line 三个属
性的解构赋值。需要注意的是,最后一次对line属性的解构赋值
之中,只有line是变量,loc和start都是模式,不是变量。
下面是嵌套赋值的例子。
3.3 字符串的解构赋值
3.4 数值和布尔值的解构赋值
3.5 函数参数的解构赋值
3.6 圆括号问题
3.6.1 不能使用圆括号的情况
3.6.2 可以使用圆括号的情况
3.7 用途
标签:console,变量,hzh,js,解构,log,赋值,hzh2,hzh1 来源: https://www.cnblogs.com/Huang-zihan/p/16248768.html