1. let person ={
  2. name:"gaojian",
  3. age:35
  4. }
  5. let {name:personName,age:personAge} =person;
  6. console.log(personName) //gaojian
  7. console.log(personAge) //35

可以简写:

  1. let person ={
  2. name:"gaojian",
  3. age:35
  4. }
  5. let {name,age} =person;
  6. console.log(name) //gaojian
  7. console.log(age) //35

解构赋值不一定与对象的属性完全匹配,赋值时可以忽略某些属性,如果引用属性不存在则赋值undefined

  1. let person ={
  2. name:"gaojian",
  3. age:35
  4. }
  5. let {name,job} = person
  6. console.log(name) //gaojian
  7. console.log(job) //undefined

也可以解构赋值时定义默认值 \如果有值 默认值会被覆盖

  1. let person ={
  2. name:"gaojian",
  3. age:35
  4. }
  5. let {name,job="software"} = person
  6. console.log(name) //gaojian
  7. console.log(job) //software

如果事先声明的变量进行赋值,则赋值表达式必须包含在一对【括号】中

  1. let person = {
  2. name: "gaojian",
  3. age: 35
  4. }
  5. let name, age;
  6. ({ name,age,job = "software"} = person)
  7. console.log(name) //gaojian
  8. console.log(age) //35
  9. console.log(job) //software

一种奇怪的现象,如果只声明了一个name 后面的也会自动被声明;

  1. let person = {
  2. name: "gaojian",
  3. age: 35,
  4. job: {
  5. title: "abc"
  6. },
  7. arr: [1, 2, 3, 4]
  8. },
  9. name;
  10. ({
  11. name,
  12. age,
  13. job = "software",
  14. arr
  15. } = person)
  16. console.log(name) //gaojian
  17. console.log(age) //35
  18. console.log(job) //{title: "abc"}
  19. console.log(arr) // [1, 2, 3, 4]

嵌套解构 可以解构来复制对象属性

  1. let person = {
  2. name: "gaojian",
  3. age: 35,
  4. job: {
  5. title: "abc"
  6. }
  7. }
  8. let name, age;
  9. ({
  10. name,
  11. age,
  12. job = "software"
  13. } = person)
  14. console.log(name) //gaojian
  15. console.log(age) //35
  16. console.log(job) //{title: "abc"}
  1. let person = {
  2. name: "gaojian",
  3. age: 35,
  4. job: {
  5. title: "abc"
  6. }
  7. }
  8. let name, age, job;
  9. ({
  10. name,
  11. age,
  12. job = "software"
  13. } = person)
  14. person.job.title = "ssss" //因为是引用地址 新job 会被修改
  15. console.log(name) //gaojian
  16. console.log(age) //35
  17. console.log(job) //{title: "ssss"}

可以进行匹配嵌套

  1. let person = {
  2. name: "gaojian",
  3. age: 35,
  4. job: {
  5. title: "abc"
  6. }
  7. }
  8. let name, age, job, mytitle;
  9. ({
  10. name,
  11. age,
  12. job: {
  13. title: mytitle
  14. }
  15. } = person)
  16. person.job.title = "ssss"
  17. console.log(name) //gaojian
  18. console.log(age) //35
  19. console.log(job); //undefined 这里会是undefined
  20. console.log(mytitle) //abc 不会被修改

如果开始赋值成功而后的赋值出错,则只会完成一部分(使用try,catch)

  1. let person = {
  2. name: "gaojian",
  3. age: 35,
  4. job: {
  5. title: "abc"
  6. }
  7. }
  8. let name, age, job, bb, mytitle;
  9. try {
  10. ({
  11. name,
  12. age,
  13. foo: {
  14. bar: bb
  15. },
  16. job: {
  17. title: mytitle
  18. }
  19. } = person)
  20. } catch (e) {
  21. console.log(e);
  22. }
  23. person.job.title = "ssss"
  24. //TypeError: Cannot read property 'bar' of undefined
  25. console.log(name) //gaojian
  26. console.log(age) //35
  27. console.log(job); //undefined
  28. console.log(mytitle) //undefined

函数参数解构

  1. let person ={
  2. name:"gaojian",
  3. age:35
  4. }
  5. function func(foo,{name,age},bar){
  6. console.log(foo,bar)
  7. console.log(name,age)
  8. }
  9. //把对象传进去调用
  10. func('1st',person,'sss') //1st gaojian 35 sss

数组的解构赋值

基本用法

  1. let [a, b, c] = [1, 2, 3];

模式匹配

只要等号两边的模式相同,左边的变量就会被赋予对应的值

  1. let [foo, [[bar], baz]] = [1, [[2], 3]];
  2. foo // 1
  3. bar // 2
  4. baz // 3
  5. let [ , , third] = ["foo", "bar", "baz"];
  6. third // "baz"
  7. let [x, , y] = [1, 2, 3];
  8. x // 1
  9. y // 3
  10. let [head, ...tail] = [1, 2, 3, 4];
  11. head // 1
  12. tail // [2, 3, 4]
  13. let [x, y, ...z] = ['a'];
  14. x // "a"
  15. y // undefined
  16. z // []

如果解构不成功,变量的值就等于undefined

  1. let [foo] = [];
  2. let [bar, foo] = [1];

另一种情况是不完全解构,即等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功。

  1. let [x, y] = [1, 2, 3];
  2. x // 1
  3. y // 2
  4. let [a, [b], d] = [1, [2, 3], 4];
  5. a // 1
  6. b // 2
  7. d // 4

上面两个例子,都属于不完全解构,但是可以成功。

如果等号的右边不是数组

(或者严格地说,不是可遍历的结构,参见《Iterator》一章),那么将会报错。

  1. // 报错
  2. let [foo] = 1;
  3. let [foo] = false;
  4. let [foo] = NaN;
  5. let [foo] = undefined;
  6. let [foo] = null;
  7. let [foo] = {};

上面的语句都会报错,因为等号右边的值,要么转为对象以后不具备 Iterator 接口(前五个表达式),要么本身就不具备 Iterator 接口(最后一个表达式)。

Set 结构,也可以使用数组的解构赋值。

  1. let [x, y, z] = new Set(['a', 'b', 'c']);
  2. x // "a"

事实上,只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值。

  • function*关键字可以在表达式内部定义一个生成器函数 (不会)
    ```javascript const foo = function*() { yield ‘a’; yield ‘b’; yield ‘c’; };

let str = ‘’; for (const val of foo()) { str = str + val; }

console.log(str); // expected output: “abc”

  1. - `yield*` 表达式迭代操作数,并产生它返回的每个值。
  2. - `yield*` 表达式本身的值是当迭代器关闭时返回的值(即`done``true`时)`<br />`
  3. ```javascript
  4. function* g1() {
  5. yield 2;
  6. yield 3;
  7. yield 4;
  8. }
  9. function* g2() {
  10. yield 1;
  11. yield* g1();
  12. yield 5;
  13. }
  14. var iterator = g2();
  15. console.log(iterator.next()); // { value: 1, done: false }
  16. console.log(iterator.next()); // { value: 2, done: false }
  17. console.log(iterator.next()); // { value: 3, done: false }
  18. console.log(iterator.next()); // { value: 4, done: false }
  19. console.log(iterator.next()); // { value: 5, done: false }
  20. console.log(iterator.next()); // { value: undefined, done: true }
  1. function* fibs() {
  2. let a = 0;
  3. let b = 1;
  4. while (true) {
  5. yield a;
  6. [a, b] = [b, a + b];
  7. }
  8. }
  9. let [first, second, third, fourth, fifth, sixth] = fibs();
  10. sixth // 5

上面代码中,fibs是一个 Generator 函数(参见《Generator 函数》一章),原生具有 Iterator 接口。解构赋值会依次从这个接口获取值。

默认值

解构赋值允许指定默认值。

  1. let [foo = true] = [];
  2. foo // true
  3. let [x, y = 'b'] = ['a']; // x='a', y='b'
  4. let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'

注意,ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,如果一个数组成员不严格等于undefined,默认值是不会生效的。

  1. let [x = 1] = [undefined];
  2. x // 1
  3. let [x = 1] = [null];
  4. x // null

上面代码中,如果一个数组成员是null,默认值就不会生效,因为null不严格等于undefined
如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值。

  1. function f() {
  2. console.log('aaa');
  3. }
  4. let [x = f()] = [1];

上面代码中,因为x能取到值,所以函数f根本不会执行。上面的代码其实等价于下面的代码。

  1. let x;
  2. if ([1][0] === undefined) {
  3. x = f();
  4. } else {
  5. x = [1][0];
  6. }

默认值可以引用解构赋值的其他变量,但该变量必须已经声明。

  1. let [x = 1, y = x] = []; // x=1; y=1
  2. let [x = 1, y = x] = [2]; // x=2; y=2
  3. let [x = 1, y = x] = [1, 2]; // x=1; y=2
  4. let [x = y, y = 1] = []; // ReferenceError

上面最后一个表达式之所以会报错,是因为x用到默认值y时,y还没有声明。