03.变量的结构赋值

1.数组的解构赋值

基本用法:

  • ES6允许按照一定模式从对象和数组中提取值,然后对变量进行赋值,称为解构;
  • 数组解构赋值本质上是一种模式匹配,只要等号两边的模式相同,左边的变量就会被赋予对应的值;
<script>
    let [a,b,c] = [1,2,3];
    console.log(a,b,c); // 1 2 3
    
    // 只要等号两边的模式匹配,就能完成解构赋值
    let [, , third] = ["aa","bb","cc"];
    console.log(third);// cc
    
    let [one,[two,[three]]] = [1,[2,[3]]];
    console.log(one,two,three);
</script>
  • 如果解构不成功,变量的值为undefined;
  • 不完全解构:等号左边的模式只能匹配一部分等号右边的数组,此时依然能够解构成功;
// 不完全解构
let [aaa,bbb] = [111,222,333];
console.log(aaa,bbb); // 111 222
  • 如果等号右边不是数组(严格来说是不可遍历的结构),将会报错,如1、false、NaN、null、undefined、{},这些值转换为对象以后不具备Iterator接口(前5个),或者本身就不具备遍历器(最后一个);
  • 结合上一条,也可以认为只要是具有Iterator接口的数据结构,都可以采用数组形式解构赋值

默认值:

  • 解构赋值允许设置默认值:在等号右边能匹配到值的前提下,默认值无效;
// 解构赋值的默认值设置
let [d = 1] = [];
console.log(d);// 1

let [x = 1] = [undefined];
x // 1

let [x = 1] = [null];// null 不全等与undefined
x // null
  • ES6内部用全等判断一个位置是否有效,因此如果一个数组成员如果不是全等于undefined,默认值是无效的
  • 如果一个默认值是一个表达式那么该表达式是惰性求值的,即只有在用到默认值时才会求值
//默认值为表达式时,表达式只有在用到时才会求值
let [a = fn()] = [];
let [b = fn()] = [222];
function fn(){
    return 1;
}
console.log(a,b); // 1 222
  • 默认值还可以是等于一个其他变量,前提是该变量必须已经声明
// 默认值也可以是其他变量(该变量需要已经被声明)
let [x = 1 , y = x] = [];
console.log(x,y);// 1 1
let [w = z , z = 1] = []
console.log(w); // 报错,z还未声明

2.对象的解构赋值

  • 对象解构与数组解构有一个重要不同:数组中的元素是按次序排列的(变量取值由位置决定),但是对象的属性是无序的,要赋值的变量需要跟属性同名才能取到正确的值
  • 对象解构赋值的内部机制是先找到同名属性,然后再赋值给相应地变量,真正被赋值的是后者
  • 常见的两种情况:
    • 变量名等于对象中的属性名;
    • 变量名不等于对象中的属性名;
// 1.变量名等于属性名:
let { a  , b } = {a :1 , b : 2};
console.log(a,b); // 1 2

// 2.变量名 !== 属性名
let{first : f , last : l} = {first : 3 , last : 4};
console.log(f,l); // 3 4
  • 与数组一样,对象解构也可以嵌套使用;
// 可以嵌套使用
let obj = {
    p : [
        "hello",
        { y : "world"}
    ]
}
let { p : [x,{y}]} = obj;
console.log(x + y); // helloworld
  • 可以设置默认值,生效的前提是对象的属性值严格等于undefined;
// 可以使用默认值,默认值生效的前提是对象的属性全等于undefined
let {q,w = 1} = {q : 11 , w : undefined};
console.log(q,w); // 11  1  w严格等于undefined,因此默认值等于1
  • 解构赋值允许左边的模式之中不放置任何变量名;
  • 对象解构可以很方便的将现有对象的某个方法赋值给变量;
// 对象解构可以很方便的将现有对象的某个方法赋值给变量
let {random,floor} = Math;
console.log(random);// ƒ random() { [native code] }
  • 数组本质是特殊的对象,因此可以对数组进行对象属性的解构;
// 数组本质是特殊的对象,因此可以对数组进行对象属性的解构
const arr = [1,2,3,4,5,6];
let {0 : first , [arr.length - 1] : last} = arr;
console.log(first,last);// 1 6

3.字符串的解构赋值

  • 字符串也可以解构赋值,此时字符串被转换成一个类似数组的对象(伪数组);
const str = "hello";
let [a,b,c,d,e] = str;  // 此时该字符串被转化成一个伪数组,具有length属性但是没有数组的方法
console.log(a,b,c,d,e); // h e l l o

4.数值和布尔值的解构赋值

  • 在使用数值和布尔值进行解构赋值时,数值(==>Number)和布尔值(==>Boolean)会先转换成对象
  • 解构赋值的规则是只要等号右边的值不是数组或对象,会先将其转换成对象
  • undefined和null无法转换成对象,所以不能对他们进行解构赋值;
// 数值和布尔值,会先被转换成对象再进行赋值
let {toString : s} = 1;
let {toString : b} = true;
// 判断s和b的toString的值是否等于对象的toString方法
console.log(s === Number.prototype.toString); // true
console.log(b === Boolean.prototype.toString); // true

5.函数参数的解构赋值

  • 函数参数也能使用解构赋值;
  • 函数参数解构能使用默认值(同样,undefined值能触发默认值);
// 函数参数使用解构赋值
    function add([x,y]) {
        console.log(x + y);
    }
    add([1,2]); // 3

    let res = [[1,2],[3,4]].map(([a,b]) => a + b);  // map遍历数组,并返回回调函数处理结果组成的新数组
    console.log(res);//[3,7]

    // 可以使用默认值
    function move({x = 0,y = 0}) {
        return [x,y];
    }
    let res1 = move({x : 1 , y : 2});
    let res2 = move({x : 1 });
    let res3 = move({});
    console.log(res1); // [1, 2]
    console.log(res2); // [1, 0]
    console.log(res3); // [0,0]

6.圆括号问题

  • 对于编译器而言,如何分别一个式子是表达式还是模式,没有办法在一开始就对此作出判断,只有在解析到(或解析不到)等号时才能确定;
  • 因此,只要有可能引起解构歧义,就不要使用圆括号
  • 建议:只要有可能,就不要在模式中使用圆括号
  • 简单来说,只要是将模式放到圆括号中,都是非法的

不能使用圆括号的情况:

  • 变量声明语句:
// 1.变量声明语句不能使用圆括号
    let [(a)] = 1;
    let {(a) : 1} = {};
  • 函数参数(也属于变量声明):
// 2.函数参数
    function test([(a)]) {
        // 哈哈哈哈哈
    }
  • 赋值语句的模式:
// 3.赋值语句中的模式
    ({ p : a })= { p :44};

可以使用圆括号的情况:

  • 赋值语句的非模式部分可以使用圆括号:
// 赋值语句的非模式部分可以使用圆括号
    [(a)] = [3];
    console.log(a); // 3

    ({p : (b)} = {p : 4});
    console.log(b);// 4

7.用途

  • 交换变量的值:
// 1. 交换变量值
let a = 1;
let b = 2;
[a,b] = [b,a];
console.log(a,b); // 2 1
  • 从函数返回多个值:
// 2. 从函数返回多个值,以数组为例(对象也同理)
function test() {
    return [1,2,3];
}
let [c,d,e] = test();
console.log(c,d,e); // 1 2 3
  • 定义函数参数:
// 3.定义函数参数
// 3.1 函数参数为有次序的值时,使用数组解构赋值
function fn1([g,h]) {
    console.log(g,h);
}
fn1([1,2]); // 1 2

// 3.1 函数参数为无次序的值时,使用对象解构赋值
function fn2({one : name , two : age}) {
    console.log(name,age);
}
fn2({one : "peanut",two : 88}); // peanut 88
  • 提取JSON数据:
// 4. 提取json数据
let jsonData = {
    name : "peanut",
    age : 33,
    learning : ['javascript','less']
}
// 数组解构赋值
let {name,age,learning : subject} = jsonData;
console.log(name,age,subject);
  • 设置函数参数默认值:
    比如设置jQuery中ajax方法的参数默认值;

  • 遍历map结构

// 5.遍历Map结构
// 5.1 获取对象的键 值
let map = new Map();
// 设置map对象的属性
map.set("first","peanut");
map.set("second","test");
for(let [key,value] of map) {
    console.log(key + " " + value);
}
// first peanut
// second test

// 只获取键
for(let [key] of map){
    console.log(key);
}
// first
// second

// 只获取值
for(let [,value] of map){
    console.log(value);
}
// peanut
// test
  • 输入模块指定的方法
// 输入模块的指定方法
const { SourceMapConsumer, SourceNode } = require("source-map");
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值