1、解构不仅可以用于数组,还可以用于对象
对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
2、指定默认值
默认值生效的条件是,对象的属性值严格等于undefined。
3、现有对象的方法
对象的解构赋值,可以很方便的将现有对象的方法,赋值到某个变量。
解构不仅可以用于数组,还可以用于对象。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>demo</title>
<script src="js/traceur.js"></script>
<script src="js/bootstrap.js"></script>
<script type="text/traceur">
var {foo,bar}={foo:"aaa",bar:"bbb"};
console.log(foo); //aaa
console.log(bar); //bbb
</script>
</head>
<body>
</body>
</html>
对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
var {bar,foo}={foo:"aaa",bar:"bbb"};
console.log(foo); //aaa
console.log(bar); //bbb
var {baz}={foo:"aaa",bar:"bbb"};
console.log(baz); //undefined
上面代码的第一个例子,等号左边的两个变量的次序,与等号右边两个同名属性的次序不一致,但是对取值完全没有影响。第二个例子的变量没有对应的同名属性,导致取不到值,最后等于†‡ˆ‹‡† undefined 。
如果变量名与属性名不一致,必须写成下面这样。
var {foo:baz}={foo:"aaa",bar:"bbb"};
console.log(baz); //aaa
let obj={first:'hello',last:'world'};
let {first:f,last:l}=obj;
console.log(f); //hello
console.log(l); //world
这实际上说明,对象的解构赋值是下面形式的简写:
var {foo:foo,bar:bar}={foo:"aaa",bar:"bbb"};
也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。
var {foo:baz}={foo:"aaa",bar:"bbb"};
console.log(baz); //aaa
console.log(foo); //foo is not defined
上面代码中,真正被赋值的是变量„ƒœ baz,而不是模式ˆ‘‘ foo。
注意,采用这种写法时,变量的声明和赋值是一体的。对于let和const来说,变量不能重新声明,所以一旦赋值的变量以前声明过,就会报错。
let foo;
let {foo}={foo:1};
console.log(foo); //报错
let baz;
let {bar:baz}={bar:1}; //报错
上面代码中,解构赋值的变量都会重新声明,所以报错了。不过,因为ƒ var 命令允许重新声明,所以这个错误只会在使用Ž‡ let 和…‘• const 命令时出现。如果没有第二个let命令,上面的代码就不会报错。Ž‡
let foo;
({foo}={foo:1});
console.log(foo); //1
let baz;
({bar:baz}={bar:1});
console.log(baz); //1
和数组一样,解构也可以用于嵌套结构的对象。
var obj={
p:[
"hello",
{y:"world"}
]
};
var {p:[x,{y}]}=obj;
console.log(x); //hello
console.log(y); //world
注意,这时’ p 是模式,不是变量,因此不会被赋值。
var node={
loc:{
start:{
line:1,
column:5
}
}
};
var {loc:{start:{line}}}=node;
console.log(line); //1
console.log(loc); //loc is not defined
console.log(start); //start is not defined
上面代码中,只有Ž‹‡ line 是变量,Ž‘… loc 和•ƒ start 都是模式,不会被赋值。
下面是嵌套赋值的例子。
let obj={};
let arr=[];
({foo:obj.prop,bar:arr[0]}={foo:123,bar:true});
console.log(obj); //{prop: 123}
console.log(arr); //[true]
对象的解构也可以指定默认值。
var {x=3}={};
console.log(x); //3
var {x,y=5}={x:1};
console.log(x); //1
console.log(y); //5
var {message:msg="something well"}={};
console.log(msg); //something well
默认值生效的条件是,对象的属性值严格等于†‡ˆ‹‡† undefined。
var {x=3}={x:undefined};
console.log(x); //3
var {x=3}={x:null};
console.log(x); //null
上面代码中,如果š x属性等于nullŽŽ ,就不严格相等于undefined†‡ˆ‹‡† ,导致默认值不会生效。
如果解构失败,变量的值等于†‡ˆ‹‡† undefined†‡ˆ‹‡†。
var {foo}={bar:'baz'};
console.log(foo); //undefined
如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错。
var {foo:{bar}}={baz:'baz'};
console.log(foo); //Cannot read property 'bar' of undefined (报错)
上面代码中,等号左边对象的 ˆ‘‘foo 属性,对应一个子对象。该子对象的„ƒ bar 属性,解构时会报错。原因很简单,因为ˆ‘‘ foo 这时等于†‡ˆ‹‡† undefined ,再取子属性就会报错,请看下面的代码。ƒ
var _tmp={baz:'baz'};
console.log(_tmp.foo.bar); //报错
如果要将一个已经声明的变量用于解构赋值,必须非常小心。
//错误写法
var x;
{x}={x:1};
console.log(x);
上面代码的写法会报错,因为JavaScript引擎会将 {x} 理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免JavaScript将其解释为代码块,才能解决这个问题。
//正确的写法
({x}={x:2});
上面代码将整个解构赋值语句,放在一个圆括号里面,就可以正确执行。关于圆括号与解构赋值的关系,参见下文。
解构赋值允许,等号左边的模式之中,不放置任何变量名。因此,可以写出非常古怪的赋值表达式。
({}=[true,false]);
({}='abc');
({}=[]);
上面的表达式虽然毫无意义,但是语法是合法的,可以执行。
对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量。
let {log,sin,cos}=Math;
上面代码将ƒŠ Math 对象的对数、正弦、余弦三个方法,赋值到对应的变量上,使用起来就会方便很多。
-----------------------------------------------------------对象的解构赋值不用按顺序----------------------------------------------------
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>对象的解构赋值不用按顺序</title>
<script src="js/traceur.js"></script>
<script src="js/bootstrap.js"></script>
<script type="text/traceur">
var {name,age,id}={id:"007",name:"lyf",age:22};
console.log(name); //lyf
console.log(age); //22
console.log(id); //007
</script>
</head>
<body>
</body>
</html>
------------------------------------------------------变量名与属性名不一致的情况----------------------
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>变量名与属性名不一致</title>
<script src="js/traceur.js"></script>
<script src="js/bootstrap.js"></script>
<script type="text/traceur">
var {personname,personage,personid}={id:"007",name:"lyf",age:22};
console.log(personname); //undefined
console.log(personage); //undefined
console.log(personid); //undefined
var {name:personname,age:personage,id:personid}={id:"007",name:"lyf",age:22};
console.log(personname); //lyf
console.log(personage); //22
console.log(personid); //007
let object={first:"Hello",last:"World"};
let {first:firstName,last:lastName}=object;
console.log(firstName); //Hello
console.log(lastName); //World
</script>
</head>
<body>
</body>
</html>
-------------------------------------------------------对象解构默认值-----------------
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>对象解构默认值</title>
<script src="js/traceur.js"></script>
<script src="js/bootstrap.js"></script>
<script type="text/traceur">
var {x="lyf"}={};
console.log(x); //lyf
var {x,y=5}={x:1};
console.log(x); //1
console.log(y); //5
var {message:msg="you are creaze"}={};
console.log(msg); //you are creaze
</script>
</head>
<body>
</body>
</html>
-----------------------------------------------
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>对象解构默认值条件</title>
<script src="js/traceur.js"></script>
<script src="js/bootstrap.js"></script>
<script type="text/traceur">
var {x=3}={x:undefined};
console.log(x); //3
var {y=3}={y:null};
console.log(y); //null (原因是:默认值生效的条件是,对象的属性值严格等于undefined。)
</script>
</head>
<body>
</body>
</html>
----------------------------已声明变量的解构赋值------------------------
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>已声明变量的解构赋值</title>
<script src="js/traceur.js"></script>
<script src="js/bootstrap.js"></script>
<script type="text/traceur">
var x;
({x}={x:1}); //不加()会报错
console.log(x); //1
</script>
</head>
<body>
</body>
</html>
------------------------------------现有对象的方法----------------------
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>现有对象的方法</title>
<script src="js/traceur.js"></script>
<script src="js/bootstrap.js"></script>
<script type="text/traceur">
console.log(Math.sin(Math.PI/6)); //0.49999999999999994
let {sin,cos,tan}=Math;
console.log(sin(Math.PI/6));//0.49999999999999994
</script>
</head>
<body>
</body>
</html>