变量的解构赋值
来源:互联网 发布:seo转行 编辑:程序博客网 时间:2024/04/30 04:49
结构赋值是ES6中新引进的概念,只要眸中数据结构具有Iterator接口,都可以采用数组形式的解构赋值。
1.数组的解构赋值
基本用法:
ES6允许按照一定得到模式,从数组和对象中提取值,对变量进行赋值,这被称作解构,在这之前,为变量赋值只能通过直接指定值,如下:
var a=0;var b=3;var c=2;
但是,ES6允许这样写:var [a,b,c] = [0,3,2];
上面的代码表示,可以从数组中提取值,按照位置的对应关系对变量赋值。
注意: 这样做的实质其实是“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予相对应的值,如下例子:
//例一let [foo,[[bar],baz]] = [1,[[2],3]];console.log(foo); //1console.log(bar); //2console.log(baz); //3//例二let [,,third] = ["dog","pig","lion"];console.log(third); //lion//例三let [x,,y] = [1,2,3];console.log(x); //1console.log(y); //3//例四let [tail,...head] = [1,2,3,4,5]; // ...是扩展符的意思console.log(tail); //1console.log(head); //[2,3,4,5]
下面看看几个结构不成功的例子,一般如果解构不成功,变量的值就会等会undefined,如下:
//例一let [a,b,...c] = ["mouse"];console.log(a); //"mouse"console.log(b); //undefinedconsole.log(c); //[]//例二var [bar] = [];var [baz,foo]=[1];console.log(bar); //undefinedconsole.log(foo); //undefined
还有 种情况是不完全解构,就是说等号左边的模式只匹配到了等号右边数组的 一部分,这种情况下,解构依然是成功的,只是不完全而已,如下:
let [a,[b],c] = [1,[2,3],4];console.log(a); //1console.log(b); //2console.log(c); //4
最后:如果等号右边不是数组,或者说等号左右两边的结构不相同,那么将会报错,下面的例子就会报错:
let [foo] = 1;let [foo] = false;let [foo] = NaN;let [foo] = undefined;let [foo] = null;let [foo] = {};
顺便说说:解构赋值不仅适用于var,也适用于let和const。
解构赋值也是允许指定默认值的,如下:
var [foo = "lion"] = [];var [x,y="mouse"] = ["pig"];var [a,b="mouse"] = ["dog",undefined];console.log(foo); //lionconsole.log(x+y); // pig+mouse;console.log(a); //dogconsole.log(b); //mouse
注意: ES6内部使用严格相等运算符(===)判断一个位置是否有值,所以,如果一个数组成员不严格等于undefined,那么解构赋值是不会生效的,如:var [x=1] = [undefined];
最后x的值还是1。
如果一个数组成员是null,这事默认值就不会生效,因为null不严格等于undefined。
如果默认值是一个表达式,那么这个表达式是惰性求值的,也就是只有在用到的时候才会求值,如:
function f(){ console.log("aaa");}let [x=f()] = [1];console.log(x); // 1
因为x可以直接取值1,所以就不会执行f()。
2.对象的解构赋值
解构不仅仅可以用在数组还可以用在对象上,如下:
var {foo,bar} = {foo:"lion",bar:"mouse"};console.log(foo); //lionconsole.log(bar); //mouse
这里,对象的解构和数组是不一样的,数组的元素是按次序排列的,变量的取值也是按照位置来决定的,但是对象就不痛,对象的属性是没有次序的,只要变量名与属性同名即可,这样才能取到正确的值,如下:
var {foo,bar,baz} = {bar:"mouse",foo:"lion"};console.log(foo); //lionconsole.log(bar); //mouseconsole.log(baz); //undefined
如果变量名与属性名不同,则必须写成下面这种:
var {foo:baz} = {foo:"lion",bar:"mouse"};console.log(baz); //lionlet obj = {first:'hello',last:'world'};let {first:f,last:l} = obj;console.log(f);console.log(l);
这表明,对象的解构赋值其实是下面这种的简写:
var {foo:foo,bar:bar} = {foo:"lion",bar:"mouse"};console.log(foo); //lionconsole.log(bar); //mouse
也就是说,对象解构赋值的内部机制,实际上是先找到同名属性,然后再赋值给同名的变量,真正被赋值的是后者,而不是前者。如:
var {foo:baz} = {bar:"mouse",foo:"lion"};console.log(baz); //lionconsole.log(foo); //error:foo is not defined
注意: 采用这种写法时,变量的声明和赋值是一体的,对于let和const而言,变量不能重复声明,所以一旦赋值的变量,在之前被声明过了,这时就会报错:
let foo;let {foo} = {foo:1};console.log(foo); //SyntaxError:Duplicate declaration "foo"let baz;let{bar:baz} = {bar:1};console.log(bar); //SyntaxError:Duplicate declaration "baz"
这个错误只会出现在let和const中,如果没有第二个let那么就不会报错了。
同样: 对象的解构赋值和数组是一样的,都可以用于嵌套结构,如下:
var obj = { loc:{ p:[ "hello", {y:"world"} ], start:{ line:"lion", column:"mouse" } }};var {loc:{p:[x,{y}],start:{line}}} = obj;console.log(x); //helloconsole.log(y); // worldconsole.log(line); // lionconsole.log(loc); // loc is not undefinedconsole.log(start); // start is not undefined
上面,只有x ,y ,line 是变量,p ,loc,start 都是模式,是不会被赋值的。
最后:对象的解构也是可以指定默认值的,其用法和数组是一致的。
3.字符串的解构赋值
字符串也是可以解构赋值的,这是因为,此时的字符串被转换成了一个类似数组的对象:
const [a,b,c,d,e] = "lion!";console.log(a); //lconsole.log(b); //iconsole.log(c); //oconsole.log(d); //nconsole.log(e); //!
类似数组的对象,都是有length属性的,因此我们还可以给这个属性解构赋值:
let {length:len} = "lion";console.log(len); // 4
4.数值和布尔值的解构赋值
解构赋值时,如果等号右边是数值或布尔值,则会先转换为对象:
let {toString:s} = 123;s===Number.prototype.toString //truelet {toString:s} = true;s===Boolean.prototype.toString //true
只要等号右边的值不是对象,就会先将其转换为对象,由于undefined与null都无法转为对象,所以对她们进行解构赋值都是会报错的:
let {lion:x} = undefined;let {mouse:y} = null;console.log(x); //TypeErrorconsole.log(y); //TypeError
5.函数参数的解构赋值
实际上,函数的参数也是可以进行解构赋值的:
function add([x,y]){ return x+y;}var n = add([2,5]);console.log(n); //7
函数参数的解构也是可以使用默认值的:
function move({x=0,y=0} = {}){ return [x,y];}var a= move({x:3,y:8});console.log(a); //[3,8]var b= move({x:3});console.log(b); //[3,0]var c= move({});console.log(c); //[0,0]var d= move();console.log(d); //[0,0]
注意下面的写法是会得到不一样的答案的:
function move({x:0,y:0} = {}){ return [x,y];}var a= move({x:3,y:8});console.log(a); //[3,8]var b= move({x:3});console.log(b); //[3,undefined]var c= move({});console.log(c); //[undefined,undefined]var d= move();console.log(d); //[0,0]
上面的代码是为函数move的参数指定默认值,而不是为变量x,y指定默认值,所以会得到不一样的结果,所以在平常写代码过程中,还是要多多留意下细节,否则,太多的Error会让人很烦恼。
6.用途
说了这么多用法,咱们来看看解构赋值都有什么样的用途,总不能有个理论,却不从使用罢。
- 交换变量的值:
交换变量的值用解构赋值是很方便的,如:[x,y] = [y,x];
这样的写法不仅简洁,而且语义很清晰。 - 从函数中返回多个值:
大家都知道,函数是只能返回一个值的,如果想要返回多个值,就只能将其放在数组或者对象中返回了,挺麻烦!但是有了解构赋值就简单的多了:
//返回一个数组function example(){ return [1,2,3,4];}var [a,b,c,d] = example();//返回一个对象function example(){ return { foo:"lion", bar:"mouse" };}var {foo,bar}= example();
- 函数参数的定义:
解构赋值可以方便的将一组参数与变量名对应起来:
//参数是一组有序的值function f([x,y,z]){......}f([1,2,3]);//参数是一组无序的值function f({x,y,z}){......}f({z:4,x:1,y:5});
- 提取Json数据:
解构赋值对提取Json对象中的数据尤为重要:
var jsondata = { id:42, status:"ok", data:[11,59]}let {id,status,data:number} = jsondata;console.log(id,status,number);// 42,ok,[11,59]
这样做是可以很快取出Json数据的值的。
- 遍历Map结构:
任何部署了Iterator接口的对象,都可以用for…..of循环遍历的,Map结构原生支持Iterator接口,再配合变量的解构赋值,获取键名和键值就非常的方便了:
var map = new Map();map.set("first","lion");map.set("second","mouse");for(let [key,value] of map){ console.log(key+"is"+value);}//first is lion//second is mouse
如果只想取键名则:
var map = new Map();map.set("first","lion");map.set("second","mouse");for(let [key] of map){ console.log(key);}//first//second
如果只想取键值则:
var map = new Map();map.set("first","lion");map.set("second","mouse");for(let [value] of map){ console.log(value);}//lion//mouse
- 变量的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- 变量的解构赋值-数组的解构
- 【ES6】变量的解构赋值
- 变量解构赋值的用途
- 变量解构赋值的用途
- Android入门基础(二)
- Class<T>和Class<?>区别
- 什么是android四大组建
- Android图片加载框架最全解析(五),Glide强大的图片变换功能
- 遍历类中参数的类型,获取需要的值
- 变量的解构赋值
- RDDs, DataFrames, and Datasets
- 分布式架构学习之:007--Dubbo 监控中心的介绍与简易监控中心的安装
- 【翻译】What really happens when you navigate to a URL
- 开源表单设计器
- [李景山php] php设计模式关键点
- Shell 学习笔记 -----运行Shell脚本的两种方法(一)
- Android中的VR简单应用
- 什么是android的广播