其他分享
首页 > 其他分享> > 第3章 变量的解构赋值

第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