解构赋值(Destructuring)

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。

数组的解构赋值

以前,为变量赋值,只能直接指定值。

let a = 1;
let b = 2;
let c = 3;

ES6 允许写成下面这样。

//等号左边是在数组中声明多个变量
//等号右边是一个数组
let [a, b, c] = [1, 2, 3];
console.log(a,b,c);//->1 2 3

上面的代码表示从,可以从数组中提取值,按照位置赋值给左侧的变量

默认值

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

//y在右侧数组中对应位置没有值,即undefined,会使用默认值
let [x,y=2]=[1] //x->1 y->2
//同上
let [x=1,y]=[,2] //x->1 y->2
//同上
let [x=1,y=2]=[] //x->1 y->2

注意,ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效。

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

默认值可以是一个表达式,只不过这个表达式是惰性的,使用到的时候才会执行求值。

function f(){ console.log("aaaaaa"); return 1; }
let [x=f()]=[];
//aaaaaa
//x->1

默认值可以引用解构赋值的其他变量,但该变量必须已经声明。

let [x = 1, y = x] = [];     // x=1; y=1
let [x = 1, y = x] = [2];    // x=2; y=2
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = [];     // ReferenceError: y is not defined

上面最后一个表达式之所以会报错,是因为x用y做默认值时,y还没有声明。

注意事项

  1. 如果解构不成功,那么变量的值将会是undefined
let [foo] = [];
let [bar, foo] = [1];

以上两种情况foo的值都是undefined

  1. 数组的解构可以用于嵌套赋值
let [x,[y,z],l]=[1,[2,3],4]
//x->1,y->2,z->3,l->4
  1. 解构存在不完全解构,即等号左边的模式,只匹配一部分等号右边的数组。这种情况下依然可以解构成功。
let [x, y] = [1, 2, 3];
x // 1
y // 2let [a, [b], d] = [1, [2, 3], 4];
a // 1
b // 2
d // 4

以上两个例子都属于不完全解构,但是够可以成功。

  1. 如果等号右边的不是数组,严格的说不是可以遍历的结果,那么将会报错。
// 报错
let [foo] = 1;          //VM415:1 Uncaught TypeError: 1 is not iterable
let [foo] = false;      //VM415:1 Uncaught TypeError: false is not iterable
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};

以上代码都会报错。

  1. 只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值
let [a,b,c]=new Set([1,2,3]);
//a->1,b->2,c->3

对象的解构赋值

解构赋值不仅可以用于数组,也可以用于对象。

//这里的变量名与对象的属性同名
let {foo,bar}={foo:"a",bar:"b"}
//foo->a bar->b

对象的解构与数组有一个重要的不同,数组中的元素是按照次序排列的,变量名的取值由他的位置决定;而对象没的属性没有次序,变量名必须与属性同名才能取到正确的值。即数组的结果是按照元素的次序给变量赋值,对象的解构是按照变量名和属性名匹配做赋值。

如果要赋值的变量名和对象属性名不一样,可以使用匹配模式:变量名称写法。

//f、b为匹配模式,会去匹配同名的属性
//将匹配到的同名属性的值赋给foo、baz
let {f:foo,b:baz}={f:"a",b:"b"}
//foo->a bar->b

其实第一个示例代码的完整写法是这样的。

//这里的变量名与对象的属性同名
let {foo:foo,bar:bar}={foo:"a",bar:"b"}
//foo->a bar->b

默认值

对象的解构赋值也可以给默认值

let {foo='a',bar}={bar:'b'} //foo->a bar->b
let {foo='a',bar='b'}={}    //foo->a bar->b
let {foo='a',bar=foo}={}    //foo->a bar->a
var { message: msg = 'Something went wrong' } = {};
//msg->"Something went wrong"

使用默认值的条件是,对象属性值严格等于(===)undefined

let {foo='a'}={foo:undefined}   //foo->a
let {foo='a'}={foo:null}        //foo->null

注意事项

  1. 对象解构失败,默认值将会是undefined,这一点和数组解构赋值一致
let {foo,bar}={foo:"a"}
//foo->a bar->undefined
  1. 对象的解构也可以用于嵌套赋值,这一点和数组的解构嵌套赋值一致
let {foo,bar:{baz}}={foo:"a",bar:{baz:"b"}}
//foo->a,bar->b

下面是一个更为复杂的例子

const node = {loc: {start: {line: 1,column: 5}}
};let { loc, loc: { start }, loc: { start: { line }} } = node;
//loc->{start: {…}}
//start->{line: 1, column: 5}
//line->1

上面的代码进行了三个解构赋值,分别是loc、start和line。这里需要注意的是:loc解构赋值时,loc即时匹配模式又是变量;start解构赋值时,loc是匹配模式,start即使匹配模式又是变量;line解构赋值时,loc\start都是匹配模式,line即是匹配模式又是变量。

  1. 如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错。
// 报错
let {foo: {bar}} = {baz: 'baz'};

foo模式需要匹配一个对象,但是foo并没有匹配到一个对象,值将会是undefinedundefined.bar会报错。

几个用于巩固知识点的代码示例

  1. 解构一个对象,赋值给数组
function test(){let array=[];let obj={foo:'a',bar:'b'};({foo:array[0],bar:array[1]}=obj);console.log("array:",array);//["a", "b"]
}
test();
  1. 解构一个数组,赋值给对象
function test1(){var obj={foo:[],bar:[]};var array = [[1,2],['a','b']];([obj.foo,obj.bar]=array);console.log("obj:",obj);//{bar:["a", "b"],foo:[1, 2]}
}
test1()
  1. 对象和数组解构赋值嵌套使用
function test2(){var obj={userName:[{fistName:'Zhang'},{lastName:'Xueyuan'}]}var userNameObj={};var userNameAray=[];({userName:[{fistName:userNameObj.fistName},{lastName:userNameObj.lastName}]}=obj);({userName:[{fistName:userNameAray[0]},{lastName:userNameAray[1]}]}=obj);console.log("userNameObj:",userNameObj);//{fistName: "Zhang", lastName: "Xueyuan"}console.log("userNameAray:",userNameAray);//["Zhang", "Xueyuan"]
}
test2()

字符串的解构赋值

字符串也可以解构赋值,如果等号的右侧是字符串,那么该字符串会转换成数组对象(Array)

let [a,b]="ab"; //a->a b->b
//上面的代码相当于
let [a,b]=new Array('a','b');

字符串转换数组对象后,也可以使用对象的解构方式解构数组对象的属性

let {length:len}="ab";  //len->2

也就是说字符串的解构赋值,既可以使用对象的解构赋值,也可以使用数组的解构赋值。

数值和布尔值的解构赋值

数值和布尔值也可以解构赋值,如果等号的右侧是数值或布尔值,那么数值或布尔值将转换正对应的包装类,数值Number,布尔值Boolean。

let {valueOf:fun}=true;
let {valueOf:fun}=123;
//这里是把valueOf函数赋值给了变量,并不是将valueOf函数的执行结果赋值给fun

注意:数值和布尔值不能使用数组解构赋值,应该两者都不是可迭代(Iteration)的对象。

函数的参数解构赋值

解构赋值可以用于数组和对象,也可以用于函数的解构赋值。原理都是一样的,一个函数需要一个或多个顺序排列的形参,在调用是顺序传入实参,使用解构数组或对象的形式作为形参,调用的时候传入数组或对象作为实参。

//普通的写法
function add(x,y){return x+y;
}
add(1,2);//->3//使用数组解构赋值的形式给函数传递参数
function add([x,y]){return x+y;
}
add([1,2]);//->3//使用对象解构赋值的形式给函数传递参数
function add({x,y}){return x+y;
}
add({x:1,y:2});//->3

默认值

函数参数的解构赋值也可以使用默认值。

//函数参数数组解构赋值指定默认值
function add([x=0,y=0]=[]){return x+y;
}
console.log(add([1,2]));//->3   相当于[x=0,y=0]=[1,2]
console.log(add([1]));//->1     相当于[x=0,y=0]=[1]
console.log(add([]));//->0      相当于[x=0,y=0]=[]
console.log(add());//->0    //使用默认值[],相当于[x=0,y=0]=[]//函数参数对象解构赋值指定默认值
function add({x=0,y=0}={}){return x+y;
}
console.log(add({x:1,y:2}));//->3    相当于{x=0,y=0}={x:1,y:2}
console.log(add({x:1}));//->1        相当于{x=0,y=0}={x:1}
console.log(add({}));//->0           相当于{x=0,y=0}={}
console.log(add());//->0    //使用默认值{},相当于{x=0,y=0}={}

注意:[x=0,y=0]=[]{x=0,y=0}={}等号左边是解构赋值的变量,右侧是调用函数不传入任何参数时使用的默认值,而不是指定x、y变量的默认值。add()调用形式会使用默认值。

默认值非{}、[]的例子

function add([x=0,y=0]=[1,2]){return x+y;
}
console.log(add([1,2]));//->3
console.log(add([1]));//->1
console.log(add([]));//->0
console.log(add());//->3    //使用默认值{},相当于[x=0,y=0]=[1,2]

用途

  1. 交替变量的值
  2. 从函数返回多个值
  3. 函数参数的定义
  4. 提取JSON
  5. 函数参数的默认值
  6. 便利Map接口
  7. 输入模块的指定方法
function forMap(){let map=new Map();map.set("name","zhangxy");map.set("age",30);for(let [key,value] of map){console.log(key,":",value);}
}
forMap();
//单独获取key
for(let [key] of map){console.log(key,":",value);
}//单独获取value
for(let [,value] of map){console.log(key,":",value);
}

总结起来解构赋值的语法让变量的赋值更简洁,用更少的代码就能从数组或对象中获取值赋给变量

学习资料:变量的解构赋值(https://es6.ruanyifeng.com/#docs/destructuring)

解构赋值(Destructuring)相关推荐

  1. ECMAScript 6的解构赋值 ( destructuring assignment)

    var provinceValues=["010","020","028","0755","023" ...

  2. 【ES6】变量的解构赋值

    [ES6]变量的解构赋值 一.什么叫解构赋值? 二.解构赋值有哪些分类?写法? 1)对数组的解构赋值 2)对对象的解构赋值 3)对字符串的解构赋值 4)对数值和布尔值的解构赋值 5)对函数参数的解构赋 ...

  3. ECMAScript6变量的解构赋值

    ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring) ###数组的解构赋值 //ES5 //var a = 1; //var b = 2; //va ...

  4. es6学习 -- 解构赋值

    ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). 以前,为变量赋值,只能直接指定值. let a = 1; let b = 2; let c ...

  5. json解析 子类和父类同名属性如何赋值_想学变量的解构赋值?看完这一篇就够了...

    序言 ES6允许按照一定模式从数组和对象中提取值,然后对变量进行复制,这被称为解构(Destructuring) 数组的解构赋值 基本用法 像上面的例子,可以从数组中提取值,按照对应位置对变量赋值,这 ...

  6. ES6的新特性(3)——变量的解构赋值

    变量的解构赋值 数组的解构赋值 基本用法 ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). let a = 1; let b = 2; le ...

  7. ECMAScript 6入门 - 变量的解构赋值

    定义 ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). 解构赋值不仅适用于var命令,也适用于let和const命令. 解构赋值的规则是,只要 ...

  8. ES6之主要知识点(二) 变量的解构赋值。默认值

    引自http://es6.ruanyifeng.com/#docs/destructuring 数组解构赋值 默认值 对象解构赋值 用途 1.数组的解构赋值 let [a, b, c] = [1, 2 ...

  9. es6分享——变量的解构赋值

    变量的解构赋值:ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). 以前的写法: var a = 1; var b = 2; es6允许的写法 ...

最新文章

  1. 【数据结构】HashMap 面试题8问
  2. html5div上下滚动,html5 – 在另一个div上滚动div
  3. 编程之美2015资格赛 题目2 : 回文字符序列 [ 区间dp ]
  4. yii2-Ueditor百度编辑器
  5. jsp项目中连接数据库解决java.lang.ClassNotFoundException: com.mysql.jdbc.Driver的问题
  6. asyncio 并发测试
  7. 第16天学习Java的笔记(标准类,Scanner)
  8. caffe源码解析—image_data_layer层
  9. 牛客 - Strange Bulbs(bitset优化拓扑)
  10. 实践 HTML5 的 CSS3 Media Queries
  11. jQuery/javascript实现全选全不选
  12. CUDA精进之路(二):图像处理——形态学滤波(膨胀、腐蚀、开闭运算)
  13. 如何自定义设置Mac OS系统和windows系统键盘的方法
  14. 移动端开发框架mui介绍
  15. 论文的中期报告怎么写?
  16. C#-概念-类库:类库
  17. docker deamon源码学习
  18. c语言小球碰壁,小球碰壁效果
  19. FreeBSD+gnome3详细安装指南
  20. A Game of Thrones(97)

热门文章

  1. Rust语言——猜数游戏
  2. html5炉石传说3d相册,HTML5 可拖曳炉石传说3D卡片
  3. python直线水平_基于直线勘测水平图像矫正——python
  4. 哈佛大学心理学博士力荐
  5. php 中basename,php中的basename函数怎么用
  6. matlab 风电厂模板解释,基于MATLAB的风电场建模仿真研究牛步柯(原稿)
  7. logstash+elastic+kibana日志管理工具介绍及安装
  8. 原码,反码,补码,阶码,移码
  9. Python爬虫系列之爬取猫眼电影,没办法出门就补一下往期电影吧
  10. jQuery移除或禁用html元素点击事件常用方法