变量的解构赋值

变量的解构赋值

  • 数组的解构赋值

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

本质:这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值;如果解构不成功值为undefined
不完全解构,即等号左边的模式,只匹配一部分的等号右边的数组。

	let [foo, [[bar], baz]] = [1, [[2], 3]];
	foo // 1
	bar // 2
	baz // 3

	let [ , , third] = ["foo", "bar", "baz"];
	third // "baz"

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

	let [head, ...tail] = [1, 2, 3, 4];
	head // 1
	tail // [2, 3, 4]

	let [x, y, ...z] = ['a'];
	x // "a"
	y // undefined
	z // []
  1. 默认值:如果一个数组成员不是严格等于undefined,默认值不会生效

     let [foo = true] = [];
     foo // true
     let [x, y = 'b'] = ['a']; // x='a', y='b'
     let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
     let [x = 1] = [undefined];
     x // 1
     let [x = 1] = [null];
     x // null
    
  • 对象的解构赋值
  1. 注意:对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

     let { bar, foo } = { foo: "aaa", bar: "bbb" };
     foo // "aaa"
     bar // "bbb"
    
     let { baz } = { foo: "aaa", bar: "bbb" };
     baz // undefined
    
  2. 对象解构赋值的本质形式

     let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };
    

本质:对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。
3. 嵌套结构的对象解构

	var node = {
	  loc: {
	    start: {
	      line: 1,
	      column: 5
	    }
	  }
	};

	var { loc, loc: { start }, loc: { start: { line }} } = node;
	line // 1
	loc  // Object {start: Object}
	start // Object {line: 1, column: 5}
  1. 对象解构的默认值;严格等于undefined时,默认值生效

     var {x = 3} = {};
     x // 3
     var {x, y = 5} = {x: 1};
     x // 1
     y // 5
     var {x: y = 3} = {};
     y // 3
     var {x: y = 3} = {x: 5};
     y // 5
     var { message: msg = 'Something went wrong' } = {};
     msg // "Something went wrong"
     var {x = 3} = {x: undefined};
     x // 3
     var {x = 3} = {x: null};
     x // null
    
  • 字符串的解构赋值:此时,字符串被转换成了一个类似数组的对象。

      const [a, b, c, d, e] = 'hello';
      a // "h"
      b // "e"
      c // "l"
      d // "l"
      e // "o"
      //还可以对属性进行解构赋值
      let {length : len} = 'hello';
      len // 5
    
  • 数值和布尔值的解构赋值:如果等号右边是数值和布尔值,则会先转为对象。

      let {toString: s} = 123;
      s === Number.prototype.toString // true
      let {toString: s} = true;
      s === Boolean.prototype.toString // true
    

解构的规则只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。

	let { prop: x } = undefined; // TypeError
	let { prop: y } = null; // TypeError
  • 函数参数的解构赋值及默认值

      function move({x = 0, y = 0} = {}) {
        return [x, y];
      }
    
      move({x: 3, y: 8}); // [3, 8]
      move({x: 3}); // [3, 0]
      move({}); // [0, 0]
      move(); // [0, 0]  
    

另一种写法,结果不一样:

	function move({x, y} = { x: 0, y: 0 }) {
	  return [x, y];
	}

	move({x: 3, y: 8}); // [3, 8]
	move({x: 3}); // [3, undefined]
	move({}); // [undefined, undefined]
	move(); // [0, 0]

原因:上面代码是为函数move的参数指定默认值,而不是为变量x和y指定默认值,所以会得到与前一种写法不同的结果。

  • 变量解构赋值的用途
  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. 提取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]
    
posted @ 2017-07-19 11:06  YFIFE  阅读(156)  评论(0编辑  收藏  举报