ES6(二):变量的解构赋值之数组,对象,字符串,数值与布尔值,函数参数

解构赋值语法是一个JavaScript表达式,这使得可以将值从数组或属性从对象提取到不同的变量中。

一.数组的解构赋值

1.普通的数组解构赋值

const arr = [1,2,3,4];
let [a,b,c,d] = arr;//a=1,b=2,c=3,d=4

2.稍复杂的匹配规则

const arr=['a','b',['c','d',['e','f','g']]];
const[ ,b]=arr;//b='b'
const[ , , g]=['e','f','g'];//g='g'
const[ , , g]=['c','d',['e','f','g']];//g=['e','f','g']
const[ , , [ , , g]]=['c','d',['e','f','g']];//g='g'

3.扩展运算符

... 可进行合并数组 [...arr1,...arr2,...arr3] 等价于arr1.concat(arr2,arr3);
const arr1=[1,2,3];
const arr2=['a','b'];
const arr3=['zz',1];
const arr4=[arr1,arr2,arr3];//[[1,2,3],['a','b'],['zz',1]]
const arr5=[...arr1,...arr2,...arr3];//[1,2,3,'a','b','zz',1]

4.拓展运算符和解构数组结合起来使用

const arr=[1,2,3,4,5,6];
const [a,b,...c]=arr;//a=1,b=2,c=[3,4,5,6]
const [a,b,...c,d]=arr;//报错

5.默认值

只有在匹配成undefined时才能设置默认值
const arr = [1,undefined,undefined];
const [a,b,c,d]=arr;//a=1,b=undefined,c=undefined,d=undefined
const [a,b=2,c,d='aaa']=arr;//a=1,b=2,c=undefined,d='aaa'
const arr1=[1,null,undefined];
const [a,b=2,c,d='aaa']=arr1;//b=null,只有是undefined时才会选择默认值

6.交换变量

 let a=20;
let b=10;
[a,b]=[b,a];//a=10,b=20

7.接收多个 函数返回值

function getUserInfo(id){
	//...ajax
	return [
		true,
        {
			name:'小明',
			gender:'女',
			id:id
        },
		'请求成功'
	];
};

const [status,data,msg]=getUserInfo(12);//status=true,data= {name:'小明',gender:'女',id:123},msg='请求成功'

二.对象的解构赋值

对象的解构赋值:①的解构赋值与数组的机构复制相似。
			   ②等号左右两边都为对象结构 const { a, b } = { a: 1, b: 2 }。
               ③左边的{}中为需要赋值的变量。
			   ④右边为需要解构的对象。
主要用途:①提取对象属性。
		 ②使用对象传入乱序的函数参数。
         ③获取多个函数返回值。

与数组不同的是,数组是靠下标匹配,对象是靠属性名匹配,属性名若是不匹配则返回undefined。
当出现了重复的对象属性名时,可以在属性名后添加:改新名字。冒号前面原本所代表的东西是不存在的,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量,真正被赋值的是后者,而不是前者。
对象的解构赋值中,与顺序无关,需要注意的是,变量名与属性名必须一致。

1.普通的对象解构赋值

const obj={
    saber:'阿尔托利亚',
    archer:'卫宫'
};
const {saber,archer1}=obj;//saber:'阿尔托利亚',archer:undefined

2.稍微复杂点的对象解构赋值

const player={
    nickname:'几位佛尔阿文',
    master:'东海龙王',
    skill:[{
        skillName:'龙吟',
        mp:'100',
        time:6000
    },{
        skillName:'龙卷雨季',
        mp:'400',
        time:3000
    },{
        skillName:'龙腾',
        mp:'900',
        time:6000
    }]
};

const {nickname}=player;// nickname:'几位佛尔阿文'
const {master}=player;// nickname:'东海龙王'
// const {skill}=player;
// const [skill1]=skill;
//类似于
const {skill:[skill1]} = player;
const {skill:[skill1,{skillName},{skillName:sklName}]} = player;//skillName='龙卷雨季',sklName='龙腾'

3.结合拓展运算符

扩展运算符...会将剩下的数据放在一个自己取名的对象中。还可用于对象的合并。
const obj={
    saber:'阿尔托利亚',
    archer:'卫宫',
    lancer:'哈佛导师'
};

const{saber,...oth}=obj;//saber='阿尔托利亚',oth={archer:'卫宫',lancer:'哈佛导师'}
用拓展运算符合并对象
const obj1={
    archer:'卫宫',
    lancer:'哈佛导师'
}
const obj={
    saber:'阿尔托利亚',
    ...obj1
}//obj={saber:'阿尔托利亚',archer:'卫宫',lancer:'哈佛导师'}

4.如何对已经申明了的变量进行对象的解构赋值

let是用在以后你还有可能再次给他赋值的时候,const 以后不能再给它赋值。
一般 const 定义方法,let 定义变量。
let age;
const obj={
    name:'小明',
    age:22
};
//{age}=obj;//报错
({age}=obj);//不推荐

更推荐:

const obj={
    name:'小明',
    age:22
};

let {age}=obj;//age=22

5.默认值

let girlfriend={
    name:'小红',
    age:22,
    food:undefined
};

let {name,age=24,food='苹果',hobby=['学习']}=girlfriend;//name='小红',age=22,food='苹果',,hobby=['学习']

例题

var {foo:baz}={foo:'aaa',bar:'bbb'};
console.log(baz)得到aaa
解析:对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。
在右面对象的内部找到与foo同名的属性 , 然后再把属性foo的值赋给变量foo(左边的为变量foo) . 然后{foo:baz} 结构赋值 , 把前面的变量foo的值赋值给后面的变量baz . 真正被赋值的是后面的变量baz , foo起到了一个中间传递的作用 , 变量foo实际上并没有赋值 ,所以不会输出"aaa" .

6.提取对象属性

const {name, hobby:[hobby1],hobby}={
    name:'小红',
    hobby:['学习']
};// name='小红',hobby1='学习',hobby:['学习'];

7.使用对象传入乱序的函数参数

function AJAX({
    url,
    data,
    type='get'
}){
    console.log(type);//get
}
AJAX({
    data:{
        a:1
    },
    url:'/getInfo',
});

8.获取多个 函数返回值

function getUserInfo(uid){
    //...ajax

    return {
        status:true,
        data:{
            name:'小红'
        },
        msg:'请求成功'
    };
};

const {status,data,msg:message} = getUserInfo(123);
//status=true, data:{name:'小红'},message='请求成功'

三.字符串的解构赋值

1.字符串的解构赋值

const str='I am the bone';

const [a,b,c,...oth] =str;//a='I',b=' ',c='a',oth=["m", " ", "t", "h", "e", " ", "b", "o", "n", "e"];
分解字符串
const [...spStr1]=str;
const spStr2=str.split();
const spStr3=[...str];
//结果都是:["I", " ", "a", "m", " ", "t", "h", "e", " ", "b", "o", "n", "e"]

2.提取属性

length属性和split()方法
const {length,split}=str;//length=13

四.数值与布尔值的解构赋值(了解)

const {valueOf} = 1;

const { toString } = true

结果

每一个类型都会有自己的一些属性和方法 ,字符串有字符串的方法 ,布尔类型有布尔类型的方法.... 
而js实际上就是把每一个类型的属性和方法包装成对象 。而每一个包装对象都会有valueof 和 toString方法 ,所以不是布尔值是toString的方法 ,而是toString是布尔类型的方法。

当然 ,上面也说了 ,并不单单布尔类型有,不管是字符串类型还是布尔类型又或者其他类型 ,都有 toString方法。

并不说str就是一个对象 ,他是一个字符串 ,只不过当你使用它的属性和方法的时候,例如str.length ,使用length 的原理就是js把str先转换为包装对象 ,然后调用对象中的length 属性。这些js自动执行的 ,他是为了获取到包装对象的方法 ,我们自己并没有手动的把它转换为对象 ,他还是一个字符串。

因为每一个类型在使用它们本身的属性或者方法的时候 ,都是这样的原理 ,所以这里只是拿字符串来举一个例子 。

五.函数参数的解构赋值

function swap([x,y]){
    return [y,x];
}
let arr=[1,2];
arr=swap(arr);//[2,1]
1、在命名规则上,构造函数一般是首字母大写,普通函数则是遵照小驼峰式命名法(小驼峰:多个单词拼接,单词首字母大小,首个单词首字母小写)。

2、调用方式不同,构造函数:构造函数内部会创建一个实例(即使用new来实例对象);

								普通函数:普通函数的调用不需要使用new来实例。

3、this的指向不同;构造函数内部的this指向是新创建的person实例,而普通函数内部的this指向调用函数的对象(如果没有对象调用,默认为window)
function Computer({
    cpu,
    memory,
    software=['ie6'],
    OS='windows 3.5'
}){
    console.log(cpu);
    console.log(memory);
    console.log(software);
    console.log(OS);
};

new Computer({
    memory:'128G',//不用按顺序
    cpu:'80286',
    OS:'windows 10'
})

六.实例总结

封装的思想
减少对全局作用域的污染
传入window和document:优化性能,函数中的变量不用去外层搜索window和document
window.person=person:可以全局访问函数person
(function (window,document){
	const FINGERS = 10;
	const HEAD = 1;
	function Person(){
		//....
	}
	window.Person2 = Person;//释放到外面
})(window,document);
定义到原型上,主要是在多次实例化的时候,会在内存中存一份,每次访问的就是同一个(原型中的行为可以被所有实例共享)。
直接写在方法中的,实例化的时候会在每个实例中再复制一份,所以消耗的内存更高。
window.$Msg = Msg表示给window声明一个为‘$msg'的变量,然后把Msg这个对象赋值给前面那个变量
(function (window,document){
	let Msg = function (options) {
    	this._init(options);
  	}
  	 Msg.prototype._init = function ({ }){};
	window.$Msg=Msg;
	
})(window,document);
注意:1.继承方法分的比较细 , 而且能够集中管理 . 能够节约代码 , 例如定义一个函数A和B , B继承A的话 , 那么父类A的属性与方法继承给B , 代码得到复用 , 减少了B的代码 . 缺点就是如果A的属性和方法修改了 , 会影响子类的属性和方法 .

2.而普通的函数 , 每个功能封装成一个函数 , 如果方法多的话 , 无法继续起来管理 , 但是优点恰恰也是因为 , 每个功能都是独立的 , 不会互相影响.

3.这两种用法在实际开发中都比较常见 , 每个方法都有自身的优点和缺点 ,需要结合实际情况 . 如普通函数优点适用于简单的组件,封装几个独立的函数 , 直接调用比较简便 . 一些大型项目 ,封装一些公共的方法 , 然后继承 , 会比较节约代码 , 利于管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值