JaneChelle | Blog JaneChelle | Blog

执着于理想,纯粹于当下

目录
学习记录2.解构赋值
/    

学习记录2.解构赋值

一、什么是解构赋值呢?

  ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值

二、分类

①.变量的解构赋值从类型分:

  1. 数组的解构赋值

    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 // []
    
  2. 对象的解构赋值
    对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

    let { bar, foo } = { foo: 'aaa', bar: 'bbb' };
    foo // "aaa"
    bar // "bbb"
    
    let { baz } = { foo: 'aaa', bar: 'bbb' };
    baz // undefined
    

    对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量。

    	// 例一
    	let { log, sin, cos } = Math;
    
    	// 例二
    	const { log } = console;
    	log('hello') // hello
    

    上面代码的例一将Math对象的对数、正弦、余弦三个方法,赋值到对应的变量上,使用起来就会方便很多。例二将console.log赋值到log变量

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

    let {length : len} = 'hello';
    len // 5
    

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

  4. 数值和布尔值的解构赋值
    解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。

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

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

    let { prop: x } = undefined; // TypeError
    let { prop: y } = null; // TypeError
    
  5. 函数参数的解构赋值
    函数的参数也可以使用解构赋值

    [1, undefined, 3].map((x = 'yes') => x);
    // [ 1, 'yes', 3 ]
    

    这段代码的解释是:
    map() 用于批量转换,括号里面可以放一个方法 这句话的意思是用map() 批量对[1, undefined, 3] 这个数组进行处理 处理的方式是 (x = 'yes') => x; 即:

    function fn(x='yes'){
      return x;
    }
    的缩写 其中(x='yes')就是x参数的默认值;
    undefined就会触发函数参数的默认值。
    ②.变量的解构赋值从结果上分:

  6. 解构成功
    此处不再举例

  7. 解构不成功
    解构不成功,变量的值就等于undefined

    let [foo] = [];
    let [bar, foo] = [1];
    
  8. 不完全解构
    等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功

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

③.变量的解构赋值从用途上分:

  1. 交换变量的值

    let x = 1;
    let y = 2;
    
    [x, y] = [y, x];
    
  2. 从函数返回多个值
    函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便

    // 返回一个数组
    function example(){
    	return [1,2,3,4]
    }
    let  [a,b,c] = example();
    // 返回一个对象
    function example() {
     return {
       foo: 1,
       bar: 2
     };
    }
    let { foo, bar } = example();
    
  3. 函数参数的定义

    function fn([x,y,z]){---}
    fn([1,2,3])
    
  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. 函数参数的默认值

    jQuery.ajax = function (url, {
     async = true,
     beforeSend = function () {},
     cache = true,
     complete = function () {},
     crossDomain = false,
     global = true,
     // ... more config
    } = {}) {
     // ... do stuff
    };
    

    指定参数的默认值,就避免了在函数体内部再写var foo = config.foo || 'default foo';这样的语句。

  6. 遍历 Map 结构
    任何部署了 Iterator 接口的对象,都可以用for...of循环遍历。Map 结构原生支持 Iterator 接口,配合变量的解构赋值,获取键名和键值就非常方便。

    const map = new Map();
    map.set('first', 'hello');
    map.set('second', 'world');
    
    for (let [key, value] of map) {
     console.log(key + " is " + value);
    }
    // first is hello
    // second is world
    
  7. 输入模块的指定方法
    加载模块时,往往需要指定输入哪些方法。解构赋值使得输入语句非常清晰。

    const { SourceMapConsumer, SourceNode } = require("source-map");
    

三、默认值

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

  1. 数组
    let [x = 1] = [undefined];
    x // 1
    
    let [x = 1] = [null];
    x // null
    

如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值.

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

这段代码的解释是:
x恒等于1,f()不会执行
上面的代码其实等价于下面的代码。

	let x;
	if ([1][0] === undefined) {
	  x = f();
	} else {
	  x = [1][0];
	}

[1]是只含元素1的数组
[0]是取数组的第0个元素
[1][0] === undefined 只是个条件判断而已,即 1 === undefined,显然是不成立的。

  1. 对象
	var {x = 3} = {x: undefined};
	x // 3
	var {x = 3} = {x: null};

默认值生效的条件是,对象的属性值严格等于undefined。
上述代码中,x属性值为null,null严格不等于undefind,默认值3不生效,最后的结果为 x = null。

  1. 函数参数
	 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]

上面代码中,函数move的参数是一个对象,通过对这个对象进行解构,得到变量x和y的值。如果解构失败,x和y等于默认值。

四、圆括号问题

  1. 不得使用圆括号
    (1)变量声明语句
    (2)函数参数
    (3)赋值语句的模式

  2. 可以使用圆括号的情况
    可以使用圆括号的情况只有一种:赋值语句的非模式部分,可以使用圆括号


标题:学习记录2.解构赋值
作者:JaneChelle
地址:https://xiao.algerfan.cn/articles/2019/08/22/1566432451469.html