3.es6-变量的解构赋值

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
初始:

let a=1,b=2,c=3;
console.log("a:",a); // 1
console.log("b:",b); // 2
console.log("c:",c); // 3

let解构赋值:

let [a,b,c]=[1,2,3];
console.log("a:",a); // 1
console.log("b:",b); // 2
console.log("c:",c); // 3
let [ , , third] = ["foo", "bar", "baz"];
console.log(third); // "baz"
// ...x   相当于x一个数组,把后面没人要的都给它
let [head, ...tail] = [1, 2, 3, 4];
console.log(head); // 1
console.log(tail); // [2, 3, 4]
  • 后面赋值项不足的情况
let [foo] = [];
console.log(foo); // undefined
let [bar, foo] = [1];
console.log("bar:",bar); // 1
console.log("foo:",foo); //undefined
let [x, y, ...z] = ['a'];
console.log(x);    // "a"
console.log(y);    // undefined
console.log(z);    // []
  • 左侧变量声明不足的情况
let [x, y] = [1, 2, 3];
console.log("x:",x);    // 1
console.log("y:",y);    // 2
// ...x   相当于x一个数组,把后面没人要的都给它
let [head, ...tail] = [1, 2, 3, 4];
console.log(head); // 1
console.log(tail); // [2, 3, 4]

如果等号的右边不是数组(或者严格地说,不是可遍历的结构),那么将会报错。

// 报错
let [foo] = 1; // Uncaught TypeError: 1 is not iterable
// iterable  可迭代的   iteration 迭代  iterator 迭代器
let [foo] = {};   // Uncaught TypeError: {} is not iterable
let [foo] = null; // Uncaught TypeError: null is not iterable
let [foo] ={a:1}; // Uncaught TypeError: {(intermediate value)} is not iterable
  • 默认值
    解构赋值允许指定默认值。
let [foo = 1] = [];
console.log(foo); // 1
let [x, y = 'b'] = ['a'];
console.log("x:",x);
console.log("y:",y);

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

let [x = 1] = [undefined];
console.log("x",x); // 1
let [y = 1] = [null];
console.log("y:",y); // null;

上面代码中,如果一个数组成员是null,默认值就不会生效,因为null不严格等于undefined。

let [x = 1, y = x] = [];     // x=1; y=1
let [x = 1, y = x] = [2];    // x=2; y=2
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = [];     // ReferenceError: y is not defined

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

  • 对象的解构赋值
let { foo, bar } = {  bar: "bbb",foo: "aaa", };  // 顺序是反着的
console.log(foo);  // "aaa"
console.log(bar);  // "bbb"

对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

let { baz } = { foo: "aaa", bar: "bbb" };
console.log(baz); // undefined

对象解构的的内部机制:eg:

let {foo, bar} = {foo: '111', bar: '222'};
console.log("foo:", foo); // 111
console.log("bar:", bar); // 222
// 等价于
let {foo: foo, bar: bar} = {foo: '111', bar: '222'};

也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。

let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
console.log(baz); // "aaa"
  • 对象解构赋值也可以指定默认值
var {x, y = 5} = {x: 1};
console.log("x:",x);    // 1
console.log("y:",y);    // 5
var {x: y = 3} = {x: 5};
console.log(y); // 5
console.log(x); // Uncaught ReferenceError: x is not defined

上面:x只是为了匹配找值,然后赋给y,所以y=5;但实际是没有声明x变量的!
默认值生效的条件是,对象的属性值严格等于undefined。(与数组是相同的)

  • 字符串的解构赋值

字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。

const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"

类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。

let {length : len} = 'hello';
console.log(len); // 5

注:只能用length属性字段,修改为其他的,是要报错的!!!!

  • 数值和布尔值的解构赋值
let {toString: s} = 123;
console.log(s); // ƒ toString() { [native code] }
console.log(s===Number.prototype.toString); // true

上面代码中,数值和布尔值的包装对象都有toString属性,因此变量s都能取到值。
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。

// Uncaught TypeError: Cannot destructure property `prop` of 'undefined' or 'null'.
let { prop: x } = undefined; 
let { prop: y } = null; 
  • 用途

(1)交换变量的值

let x = 1;
let y = 2;

[x, y] = [y, x];

(2)从函数返回多个值
函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便。

// 返回一个数组

function example() {
  return [1, 2, 3];
}
let [a, b, c] = example();

// 返回一个对象

function example() {
  return {
    foo: 1,
    bar: 2
  };
}
let { foo, bar } = example();

(3)函数参数的定义
解构赋值可以方便地将一组参数与变量名对应起来。

// 参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);

// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});

(4)提取 JSON 数据
解构赋值对提取 JSON 对象中的数据,尤其有用。

let jsonData = {
  id: 42,
  status: "OK",
  data: [867, 5309]
};

let { id, status, data: number } = jsonData;

console.log(id, status, number);
// 42, "OK", [867, 5309]

(5)函数参数的默认值

(6)遍历 Map 结构

猜你喜欢

转载自blog.csdn.net/weixin_42995876/article/details/86530216