通俗易懂理解ES6 - 变量的解构赋值

引言

万丈高楼平地起,欲练此功,必先打好基本功: )
编程语言总少不了变量赋值;ES6中引入了新的赋值形式:解构赋值;解构赋值大大的简化了变量赋值的代码,解构赋值仅能对具有迭代器(Iterator)的数据使用;

什么是迭代器(Iterator)?这有两篇文章可以参考一下(对阅读下文会有帮助):

我本人对iterator的总结理解

阮一峰老师写的极客学院文章


赋值和解构赋值

解构赋值,直白地理解就是 解析解构进行赋值~
在ES5中,我们对变量的赋值是这样的

var a = {item: 'obj',item1: 'obj1'},
    b = ['c1','c2','c3'],
    c = 'test',
    d = 'test2'
var item = b.item,
    item1 = b.item1,
    item2 = b.item2,
    arrItem = c[0],
    arrItem1 = c[1];
item;       //obj
item1;      //obj1
item2;      //undefined
arrItem;    //c1
arrItem1;   //c2
复制代码

emmmmm...好麻烦~
再看看使用ES6解构赋值的写法:

let a = {item: 'obj',item1: 'obj1'},
    b = ['c1','c2','c3'];
let {item,item1,item2} = a,
    [arrItem,arrItem1] = b,
    [,,arrItem2,arrItem3] = b;
item;       //obj
item1;      //obj1
item2;      //undefined
arrItem;    //c1
arrItem1;   //c2
arrItem2;   //c3
复制代码

没有对比就没有伤害,使用解构赋值可以在一定程度上减少代码量,且代码赋值形式简洁、直观;解构赋值不仅适用于let命令,constvar同样适用。

解构赋值仅允许等号右边的对象是存在遍历器(Iterator)的对象。 如下是错误的解构赋值示例:

let [item] = 1;
let [item] = {};
let [item] = NaN;
let [item] = null;
let [item] = false;
let [item] = undefined;
复制代码

解构赋值允许赋值时对变量指定默认值。

//ES5
let obj = {item1: 'test'},
    item1 = obj.item1,
    item2 = obj.item2;
item2;      //空字符串
    
//ES6
let obj = {item1: 'test'},
    { item1='',item2='' } = obj;
item2;      //空字符串
复制代码

比对ES5的赋值形式和ES6的解构赋值,变量item2在ES5的赋值形式下,由于obj不存在item2属性,导致item2得到undefined的值,而ES6的解构赋值,可在赋值进行时对变量预留默认值,避免赋值的变量得到undefined的值;它的效果可理解为

let item1 = obj.item1 || '',
    item2 = obj.item2 || '';
复制代码

解构赋值在解构失败时,若变量没有预留默认值,得到的值也会是undefined。

let obj = {a: 'string'},
    [b,c] = ['test'],
    {d} = obj;
b;      //test
c;      //undefined
d;      //undefined
复制代码

以上情况就是个别变量存在解构失败的示例,变量b对应的是test,c无对应值,obj.d不存在,且cd未设置默认值,因此cd解构失败,得到的值就为undefined

当且仅当变量对应的取值的数据为undefined时,默认值才会生效

let a = {b: null},
   {b='test'} = a;
b;  // null
let [c='test'] = [undefined];
c;  //test
let [d='test',e='www'] = [NaN,null];
d;  //NaN
e;  //null
复制代码

ES6内部使用严格相等符===判断一个值是否等于undefined,当且仅当值是undefined,默认值才会生效。

若解构赋值中,指定的默认值是一个函数表达式,则该表达式当且仅当在用到的时候才会求值

let fn = () => {
    return '123';
};
let [a=fn(),b=fn()] = [1];
a;      //1
b;      //123
复制代码

在某些场合下,解构赋值也可以将某些对象的方法简便命名调用

let { assign, freeze } = Object;
let a = assign({},{b:1}),
    b = freeze(a);
a;      //{b: 1}
b;      //{b: 1}
复制代码

将一个已被变量声明过的变量用于解构赋值时,需要把解构赋值表达式放在()内

let a = 'test';
{a} = {a: 'obj test'};          //报错:Uncaught SyntaxError: Unexpected token =
({a} = {a: 'obj test'});        //a等于  obj test
复制代码

这是因为在JavaScript解释的过程中,行首是"{"的话,JavaScript会把"{}"包起来的代码解释为一个代码块,导致语法错误;而我们实际需要执行的是{a} = {a: 'obj test'}这样整个赋值过程,因此需要用"()"包起来,避免{出现在行首。

对对象进行解构赋值时,不要求变量名必须与属性名一致,但命名赋值方式会稍有区别

let man = {name:'john',sex:'male',height:'177cm',weight:'70kg',interest:'climbing'};
let {name: mans_name,sex:sexal,height:tall,job:works='u guess'} = man;
mans_name;      //john
sexal;          //male
tall;           //177cm
works;          //u guess
name;           //Uncaught ReferenceError: name is not defined
复制代码

let {name: mans_name} = man;代表将man.name的值赋值给变量名为mans_name的变量,其他变量同理,该赋值形式同样可以设置默认值,如变量works;

解构赋值适用于函数参数

function Human({name='',sex='female',age}) {
    if(sex==='male') {
        console.log('u must be a handsome guys!');
    }else if(sex === 'female') {
        console.log('u must be a beauty!');
    }else {
        console.log('exm,r u seriouse?');
    }
    console.log(name);
    console.log(sex);
    console.log)(age);
}
let character = {sex:'male',name:'Allen',age:27}
Human(character); 
//  u must be a handsome guys!
//  Allen
//  male
//  27
复制代码

当参数为undefined时,也会触发默认值生效,如sex参数,当不传sex参数时,sex会得到默认值female

解构赋值同样适用于字符串

let [a,b,c,d] = 'test',
a;          //t
b;          //e
c;          //s
d;          //t
复制代码

解构赋值时,若等号右侧是一个字符串形式的值,解构赋值的处理操作会把右侧字符串转变成类似数组形式的解构进行对变量的解构赋值。 数组对象都具有length属性,因此类数组的对象也必须具有length属性,如下代码块也同样成功执行赋值。

let {length: len} = 'test';
len;        //4
复制代码

对数值类型和布尔型数据进行解构赋值

let {a,toString} = 123;
a;      //undefined
toString === Number.prototype.toString;      //true

let {b,toString} = true;
b;      //undefined
toString === Boolean.prototype.toString;     //true
复制代码

上述两个示例,右侧的值由于可被对象化(Number、Boolean),对象化后均存在toString属性,因此toString变量等同于相应右侧值对象化后的prototype.toString方法。而a、b均是对象化后不存在的属性,因此得到的值就为undefined。

解构赋值的规则是,等号右侧若是对象类型,则直接进行解构赋值,若不是对象类型,会把对象类型转换为对象类型,再进行解构赋值,转换失败,解构赋值失败。


解构赋值的多功能用途

解构赋值能简化变量交换值

let a = 1,b = 2;
[a,b] = [b,a];
a;          //2
b;          //1
复制代码

解构赋值简化对函数返回值取值操作

function test() {
    return {a:'a',b:'b',c:'c'};
};
let {a,b,c} = test();
a;      //a
b;      //b
c;      //c
复制代码

解构赋值简化键值数据获取方式和数据赋值容错写法

let map = new Map();
map.set('test','javacript').set('do','something');
for(let [key,value] of map) {
   console.log(key + ' ' + value);
}
//test javascript
//do something

let obj = {},
   {a='原本是undefined,现在是有个这个字符串的值'} = obj;
a;     //原本是undefined,现在是有个这个字符串的值
复制代码

对import、require引入的模块加载指定的方法或数据

import {Ajax_Interface,Format_Interface} from '~/Interface_Configs.js';
const {RouterConfigs, PageConfigs} = require('Common-Configs');
复制代码

对解构赋值的一些总结

ES6提供的解构赋值让赋值操作变得更具有可读性,对变量能预留默认值,避免数据操作过程中由undefined所导致的一些报错情况。把解构赋值用于函数参数处理上,有效避免参数无序传入导致取参麻烦的问题。

以上。

文章观点内容如有错误欢迎指出交流,相互进步

转载于:https://juejin.im/post/5cc46f7f6fb9a031e9752610

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值