解构赋值
Posted mj-my
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解构赋值相关的知识,希望对你有一定的参考价值。
<script type="text/javascript">
/*传统赋值*/
function tradition(){
let a=1;
let b=2;
let c=3;
};
tradition();
/*ES6赋值*/
function ES6(){
//1.数组的解构赋值
this.assignment=function(){
let [a,b,c] = [1,2,3];
console.log([a,b,c]);//1,2,3
let [foo,[[bar],jpg]] = [1,[[2],3]];
console.log([foo,[[bar],jpg]]);//[1,[2,[3]]]
let [,,third] = ["foo",‘bar‘,‘123‘];
console.log([,,third]);//exmpt,exmpt,123
let [x, , y] = [1, 2, 3,[1,2,3]];
console.log([x, , y]);//1,exmpt,3
let [head,...tail] = [1,2,3,4,5];
console.log(head,tail);//1,[2,3,4,5]
let [yy,ll,...qq] = [‘a‘];
console.log(yy,ll,qq)//a undefined []
/*总结:左右对等:结果一样,变量多多值少:打印出被赋值的变量,没有赋值成功的变量则为undefined。变量少值多:打印出赋值的变量,属于不完全结构,但可以成功赋值*/
};
//如果右边不是数组。严格来说,不是可遍历的结构,那么将会报错,
this.errorArray=function(){
let[foo]=1;
let[foo]=false;
let[foo]=NaN;
let[foo]=undefined;
let[foo]=null;
let[foo]={};
/*上面语句都会报错,因为上面前五个的值转为对象以后不具备Iterator接口,最后一个本身就不具备Iterator接口*/
};
//对于Set结构,我们还可以用数组的解构赋值。
this.set=function(){
let[x,y,z,g] = new Set([‘a‘,‘b‘,‘c‘]);
console.log(x,y,z,g)//a,b,c undefined
};
//只有某种数据结构具有Iterator接口,都可以采用数组形式的结构赋值。
this.Iterator=function(){
function* fibs(){
let a=0;
let b=1;
while (true){
yield a;
[a,b]=[b,a+b];
};
};
let [first, second, third, fourth, fifth, sixth] = fibs();
console.log(sixth);//5
};
//默认值:解构赋值允许默认值,还可以引用结构赋值的其他变量,但该变量必须已经声明。
this.defaultValue=function(){
let[foo = true] = [];
console.log(foo);//true
let[x,y="b"] =[1];
console.log(x,y);//1,b
let [xx, yy = ‘b‘] = [‘a‘, undefined]; // x=‘a‘, y=‘b‘
console.log(xx,yy);//1,b
let [num = 1] = [undefined];
console.log(num);
let [Number = 1] = [null];
console.log(Number);
let [bgg=num,xm=Number] = [undefined];
console.log(bgg,xm);
let [h=num,t=h] = [1,5];
console.log(h,t);
/*总结:es6内部使用严格相等运算符(===),判断一个位置是否具有值,所以,只有当一个数组成员严格等于undefined,默认值才会生效*/
};
//表达式:惰性执行
this.expression=function(){
function f(){
console.log("aaa");
};
let [ff = f()]=[1];
//上面的代码等价于下面的代码。同样也是只要右边有赋值,就不会执行默认值的函数。
let func;
if([1][0]===undefined){
func=f();
}else{
func=[1][0];
};
console.log(func)
};
//2.对象的解构赋值,
/*对象的解构与数组有一个重要的不同,数组的元素是按照次序排列的,变量的取值由它的位置界决定,而对象的属性没有次序,变量必须与属性同名,才能渠道正确的值。*/
this.obj =function(){
console.log("this.obj:对象的解构赋值");
let{foo,bar} = {foo:[{id:"1",name:"你好"},{id:"2",name:"你好000"}],bar:"bbb"};
console.log(foo,bar);
//变量没有对应的同名属性,导致取不到值,最后等于undefined。
let {bzz}={foo:"aaa",bar:"bbb"};
console.log(bzz)//undefined;
//1.次序颠倒
let{foot,baz} = {baz:"baz",foot:"foot"};
console.log(foot,baz)//foot,baz
//如果变量名与属性名不一致,必须写成下面这样。
let {footer:header,hed:head} = {footer:‘aaa‘,hed:"bbb"};
console.log(header,head)//aaa,bbb
//这实际上说明,对象的解构赋值是上面形式的简写。
let obj = {first:"hello",last:‘world‘};
let {first:f,last:l} =obj;
console.log(f,l)//heoll,world;
let { num: num2 } = { num: "aaa", num2: "bbb" };
//num2 "aaa"
//num error: foo is not defined
//上面代码中,num是匹配的模式,num2才是变量。真正被赋值的是变量num2,而不是模式num。
//2.和数组一样,解构也可以用于嵌套结构的对象
let obje = {
p:[
"hello",
{y:"world"}
],
};
let{p:[x,{y}]} =obje;
console.log(x,y)//heoll,world
let{p:bgg} =obje;
console.log(bgg)//obje对象
//p并不是变量。如果想要p成为变量
let{p,p:[xx,{yy}]} = obje;
console.log(p)//obje对象
const noded = {
loc: {
start: {
line: 1,
column: 5
}
}
};
let { loc, loc: { start }, loc: { start: { line }} } = noded;
console.log(loc);//start: {line: 1,column: 5};
console.log(start);//{line: 1,column: 5};
console.log(line);//1;
/*注意,最后一次对line属性的解构赋值之中,只有line是变量,loc和start都是模式,不是变量。*/
};
/*下面是嵌套赋值的例子*/
this.nest =function(){
console.log("this.nest:下面是嵌套赋值的例子");
let Object ={};
let arr = {};
({boo:Object.prop,zar:arr[0]}={boo:123,zar:true});
console.log(Object,arr);
};
/*对象的解构也可以指定默认值*/
this.objMore=function(){
console.log("this.objMore:对象的解构也可以指定默认值")
var {x = 3}={};
console.log(x)//3
var {x,y=5}={x:1};
console.log(x,y)//1,5
var {x:y=3}={x:5};
console.log(y)//5
/*默认值生效的条件是,对象的属性值严格等于undefined。*/
var {b=3} = {b:undefined};
console.log(b)//3
var {b=3} = {b:null};
console.log(b)//null
//如果解构失败,变量的值等于undefined。
let{bgg} = {bar:"bza"};
console.log(bgg)//undefined
//如果子对象的父属性没有被定义,则会报错
//var {foo: {bart}} = {baz: ‘baz‘,};
//console.log({bart});
//下面的定义了就不会报错。
let {foo: {bart}} = {foo:{bart:{id:1}},baz: ‘baz‘,};
console.log({bart})
}
//对象语法圆括号和花括号问题
this.garmmar=function(){
//如果将一个已经声明的变量进行解构赋值,要非常小心
let x;
//{x}={x:1};
//报错原因:js引擎会将{x}解析成代码块,而并不是一个对象,只有将花括号不写在首行就行。
({x}={x:1});
console.log(x);//1
/*解构赋值允许等号左边的模式中不放置任何变量,这个是合法的,但是毫无意义*/
({}={x:1});
({}=[true,false]);
({}=[]);
({}="abc");
//对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量。
let { log, sin, cos } = Math;
console.log(log);
//由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。
let array =[1,2,3];
let {0:first,[array.length-1]:last}=array;
console.log(first,last);//1,3
};
/*字符串的解构赋值*/
this.stringF=function(){
/*字符串也可以解构赋值。字符串被转换成了一个类似数组的对象。*/
const [a,b,c,d,e] = "hello";
console.log(a,b,c,d,e)//h e l l o
/*既然可以转化为数组,那么必然会有length*/
const{length:len} ="hello";
console.log(len);
};
/*4.数值和布尔值的解构赋值*/
/*解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。*/
this.booleanAndnumber=function(){
var {toString:s} =123;
console.log(s === Number.prototype.toString);
var {toString:s} =true;
console.log(s === Boolean.prototype.toString);
/*解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。*/
//var { prop: x } = undefined; // TypeError
//var { prop: y } = null; // TypeError
};
//5.函数参数的解构赋值
this.func=function(){
function add([x,y]){
return x+y;
};
console.log(add([1,2]));//3
[[1,2],[3,4]].map(function([a,b]){
console.log([a,b])//[1,2],[3,4]
return a+b,console.log(a+b);//3,7
});
/*函数参数的解构也可以用默认值*/
function move({x=12,y=12}={}){
return [x,y];
};
move();//24
move({x:24,y:24});//48
move({});
//注意,下面的写法会得到不一样的结果。
function moved({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
moved({x: 3, y: 8}); // [3, 8]
moved({x: 3}); // [3, undefined]
moved({}); // [undefined, undefined]
moved(); // [0, 0];
//undefined就会触发函数参数的默认值。
[1,undefined,3].map(function(x="yes"){
console.log(x)//1,yes,3
});
};
//圆括号的问题
this.roundBrackets=function(){
//不能使用圆括号的3中方式
/*1.变量声明语句*/
//let [(a)] = [1];报错,缺少括号
// var {x:(c)}={}//虽然内部是正确的,但是被声明了。
// var {(x):c}={}//内部都是错的,不能使用在模式上面。
// var ({x: c}) = {};//内部错了,并且声明了语句。圆括号不能包裹模式。
// var {(x: c)} = {};//同上。
// /*2.函数参数*/
// /*函数参数也属于变量声明,因此不能带有圆括号。*/
// function f([(z)]){return z;};
// function ff(([z,(x)]))(return x;);
//
// //3.赋值语句的模式
// ({p:a})={p:42};
// ([a]) = [5];
// [({p:a}),{x:c}]=[{},{}];
// 都是缺少括号,都报错
/*可以使用圆括号的情况只有一种:赋值语句的非模式部分。*/
[(b)] = [3]; // 正确
console.log((b));//3
({p:(a)}= {p:12});
console.log(a);
[(parseInt.prop)]=[3];
console.log(parseInt.prop);
};
/*用途*/
this.user=function(){
/*1.交换变量的值*/
let x=1;
let y=2;
[x,y]= [y.x];//2,1
/*2.从函数返回多个值*/
/*返回一个数组*/
function arr (){
return[1,2,3];
};
let [a,b,c] = arr();
console.log(a,b,c)//1,2,3
/*返回一个对象*/
function obj(){
return{
foo:1,
bar:2
};
};
let{foo,bar}=obj();
console.log(foo,bar);//1,2
//(3)函数参数的定义
//解构赋值可以方便地将一组参数与变量名对应起来。
// 参数是一组有次序的值
function wellf([x, y, z]) { /*...*/ };
wellf([1, 2, 3]);
// 参数是一组无次序的值
function unordered({x, y, z}) { /*...*/ };
unordered({z: 3, y: 2, x: 1});
//(4)提取 JSON 数据
//解构赋值对提取 JSON 对象中的数据,尤其有用。
let jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]
//(5)遍历 Map 结构
//任何部署了 Iterator 接口的对象,都可以用for...of循环遍历。Map 结构原生支持 Iterator 接口,配合变量的解构赋值,获取键名和键值就非常方便。
const map = new Map();
map.set(‘first‘, ‘hello‘);
map.set(‘second‘, ‘world‘);
for (let [key, value] of map) {
console.log(key + " is " + value);
};
// first is hello
// second is world
//如果只想获取键名,或者只想获取键值,可以写成下面这样。
// 获取键名
for (let [key] of map) {
// ...
};
// 获取键值
for (let [,value] of map) {
// ...
};
//(6)输入模块的指定方法
//加载模块时,往往需要指定输入哪些方法。解构赋值使得输入语句非常清晰。
const { SourceMapConsumer, SourceNode } = require("source-map");
};
};
var modern = new ES6();
modern.assignment();
modern.set();
modern.Iterator();
modern.defaultValue();
modern.expression();
modern.obj();
modern.nest();
modern.objMore();
modern.garmmar();
modern.stringF();
modern.booleanAndnumber();
modern.func();
modern.roundBrackets();
modern.user();
</script>
以上是关于解构赋值的主要内容,如果未能解决你的问题,请参考以下文章