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

44次阅读

共计 4122 个字符,预计需要花费 11 分钟才能阅读完成。

引言

万丈高楼平地起,欲练此功,必先打好基本功: )

编程语言总少不了变量赋值;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  = [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 所导致的一些报错情况。把解构赋值用于函数参数处理上,有效避免参数无序传入导致取参麻烦的问题。

以上。

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

正文完
 0