原文鏈接:小邵教你玩轉(zhuǎn)ES6
解構(gòu)賦值
解構(gòu)賦值主要分為對象的解構(gòu)和數(shù)組的解構(gòu)息罗,在沒有解構(gòu)賦值的時候,我們賦值是這樣的
let arr = [0,1,2]
let a = arr[0]
let b = arr[1]
let c = arr[2]
這樣寫很繁瑣洪鸭,那么我們有沒辦法既聲明挡毅,又賦值蒜撮,更優(yōu)雅的寫法呢?肯定是有的慷嗜,那就是解構(gòu)賦值淀弹,解構(gòu)賦值,簡單理解就是等號的左邊和右邊相等庆械。
一薇溃、數(shù)組的解構(gòu)賦值
let arr = [0,1,2]
let [a,b,c] = arr
console.log(a) // 0
console.log(b) // 1
console.log(c) // 2
但是很多時候,數(shù)據(jù)并非一一對應(yīng)的缭乘,并且我們希望得到一個默認(rèn)值
let arr = [,1,2]
let [a='我是默認(rèn)值',b,c] = arr
console.log(a) // '我是默認(rèn)值'
console.log(b) // 1
console.log(c) // 2
從這個例子可以看出沐序,在解構(gòu)賦值的過程中,a=undefined時堕绩,會使用默認(rèn)值
那么當(dāng)a=null時呢策幼?當(dāng)a=null時,那么a就不會使用默認(rèn)值奴紧,而是使用null
// 數(shù)組的拼接
let a = [0,1,2]
let b = [3,4,5]
let c = a.concat(b)
console.log(c) // [0,1,2,3,4,5]
let d = [...a,...b]
console.log(d) // [0,1,2,3,4,5]
// 數(shù)組的克隆
// 假如我們簡單地把一個數(shù)組賦值給另外一個變量
let a = [0,1,2,3]
let b = a
b.push(4)
console.log(a) // [0,1,2,3,4]
console.log(b) // [0,1,2,3,4]
因為這只是簡單的把引用地址賦值給b特姐,而不是重新開辟一個內(nèi)存地址,所以
a和b共享了同一個內(nèi)存地址黍氮,該內(nèi)存地址的更改唐含,會影響到所有引用該地址的變量
那么用下面的方法,把數(shù)組進(jìn)行克隆一份沫浆,互不影響
let a = [0,1,2,3]
let b = [...a]
b.push(4)
console.log(a) // [0,1,2,3]
console.log(b) // [0,1,2,3,4]
二捷枯、對象的解構(gòu)賦值
對象的解構(gòu)賦值和數(shù)組的解構(gòu)賦值其實類似,但是數(shù)組的數(shù)組成員是有序的
而對象的屬性則是無序的专执,所以對象的解構(gòu)賦值簡單理解是等號的左邊和右邊的結(jié)構(gòu)相同
let {name,age} = {name:"swr",age:28}
console.log(name) // 'swr'
console.log(age) // 28
對象的解構(gòu)賦值是根據(jù)key值進(jìn)行匹配
// 這里可以看出淮捆,左側(cè)的name和右側(cè)的name,是互相匹配的key值
// 而左側(cè)的name匹配完成后本股,再賦值給真正需要賦值的Name
let { name:Name,age } = { name:'swr',age:28 }
console.log(Name) // 'swr'
console.log(age) // 28
那么當(dāng)變量已經(jīng)被聲明了呢攀痊?
let name,age
// 需要用圓括號,包裹起來
({name,age} = {name:"swr",age:28})
console.log(name) // 'swr'
console.log(age) // 28
變量能否也設(shè)置默認(rèn)值拄显?
let {name="swr",age} = {age:28}
console.log(name) // 'swr'
console.log(age) // 28
// 這里規(guī)則和數(shù)組的解構(gòu)賦值一樣蚕苇,當(dāng)name = undefined時,則會使用默認(rèn)值
let [a] = [{name:"swr",age:28}]
console.log(a) // {name:"swr",age:28}
let { length } = "hello swr"
console.log(length) // 9
function ajax({method,url,type='params'}){
console.log(method) // 'get'
console.log(url) // '/'
console.log(type) // 'params'
}
ajax({method:"get",url:"/"})
三凿叠、擴(kuò)展運(yùn)算符
我們先看下代碼,在以往,我們給函數(shù)傳不確定參數(shù)數(shù)量時盒件,是通過arguments來獲取的
function sum() {
console.log(arguments) // { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5, '5': 6 }
// 我們可以看出蹬碧,arguments不是一個數(shù)組,而是一個偽數(shù)組
let total = 0
let { length } = arguments
for(let i = 0;i < length;i++){
total += arguments[i]
}
return total
}
console.log(sum(1,2,3,4,5,6)) // 21
接下來我們用擴(kuò)展運(yùn)算符看看
function sum(...args){ // 使用...擴(kuò)展運(yùn)算符
console.log(args) // [ 1, 2, 3, 4, 5, 6 ] args是一個數(shù)組
return eval(args.join('+'))
}
console.log(sum(1,2,3,4,5,6)) // 21
得到的args是一個數(shù)組炒刁,直接對數(shù)組進(jìn)行操作會比對偽數(shù)組進(jìn)行操作更加方便恩沽,還有一些注意點需要注意
// 正確的寫法 擴(kuò)展運(yùn)算符只能放在最后一個參數(shù)
function sum(a,b,...args){
console.log(a) // 1
console.log(b) // 2
console.log(args) // [ 3, 4, 5, 6 ]
}
sum(1,2,3,4,5,6)
// 錯誤的寫法 擴(kuò)展運(yùn)算符只能放在最后一個參數(shù)
function sum(...args,a,b){
// 報錯
}
sum(1,2,3,4,5,6)
我們可以對比下擴(kuò)展運(yùn)算符的方便之處
// 以往我們是這樣拼接數(shù)組的
let arr1 = [1,2,3]
let arr2 = [4,5,6]
let arr3 = arr1.concat(arr2)
console.log(arr3) // [ 1, 2, 3, 4, 5, 6 ]
// 現(xiàn)在我們用擴(kuò)展運(yùn)算符看看
let arr1 = [1,2,3]
let arr2 = [4,5,6]
let arr3 = [...arr1,...arr2]
console.log(arr3) // [ 1, 2, 3, 4, 5, 6 ]
// 以往我們這樣來取數(shù)組中最大的值
function max(...args){
return Math.max.apply(null,args)
}
console.log(max(1,2,3,4,5,6)) // 6
// 現(xiàn)在我們用擴(kuò)展運(yùn)算符看看
function max(...args){
return Math.max(...args) // 把a(bǔ)rgs [1,2,3,4,5,6]展開為1,2,3,4,5,6
}
console.log(max(1,2,3,4,5,6)) // 6
// 擴(kuò)展運(yùn)算符可以把a(bǔ)rgument轉(zhuǎn)為數(shù)組
function max(){
console.log(arguments) // { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5, '5': 6 }
let arr = [...arguments]
console.log(arr) // [1,2,3,4,5,6]
}
max(1,2,3,4,5,6)
// 但是擴(kuò)展運(yùn)算符不能把偽數(shù)組轉(zhuǎn)為數(shù)組(除了有迭代器iterator的偽數(shù)組,如arguments)
let likeArr = { "0":1,"1":2,"length":2 }
let arr = [...likeArr] // 報錯 TypeError: likeArr is not iterable
// 但是可以用Array.from把偽數(shù)組轉(zhuǎn)為數(shù)組
let likeArr = { "0":1,"1":2,"length":2 }
let arr = Array.from(likeArr)
console.log(arr) // [1,2]
對象也可以使用擴(kuò)展運(yùn)算符
// 以往我們這樣合并對象
let name = { name:"邵威儒" }
let age = { age:28 }
let person = {}
Object.assign(person,name,age)
console.log(person) // { name: '邵威儒', age: 28 }
// 使用擴(kuò)展運(yùn)算符
let name = { name:"邵威儒" }
let age = { age:28 }
let person = {...name,...age}
console.log(person) // { name: '邵威儒', age: 28 }
需要注意的是翔始,通過擴(kuò)展運(yùn)算符和Object.assign對對象進(jìn)行合并的行為罗心,是屬于淺拷貝,那么我們在開發(fā)當(dāng)中城瞎,經(jīng)常需要對對象進(jìn)行深拷貝渤闷,接下來我們看看如何進(jìn)行深拷貝。
方法一:利用JSON.stringify和JSON.parse
let swr = {
name:"邵威儒",
age:28,
pets:['小黃']
}
let swrcopy = JSON.parse(JSON.stringify(swr))
console.log(swrcopy) // { name: '邵威儒', age: 28, pets: [ '小黃' ] }
// 此時我們新增swr的屬性
swr.pets.push('旺財')
console.log(swr) // { name: '邵威儒', age: 28, pets: [ '小黃', '旺財' ] }
// 但是swrcopy卻不會受swr影響
console.log(swrcopy) // { name: '邵威儒', age: 28, pets: [ '小黃' ] }
這種方式進(jìn)行深拷貝脖镀,只針對json數(shù)據(jù)這樣的鍵值對有效
對于函數(shù)等等反而無效飒箭,不好用,接著繼續(xù)看方法二蜒灰、三弦蹂。
方法二
function deepCopy(fromObj,toObj) { // 深拷貝函數(shù)
// 容錯
if(fromObj === null) return null // 當(dāng)fromObj為null
if(fromObj instanceof RegExp) return new RegExp(fromObj) // 當(dāng)fromObj為正則
if(fromObj instanceof Date) return new Date(fromObj) // 當(dāng)fromObj為Date
toObj = toObj || {}
for(let key in fromObj){ // 遍歷
if(typeof fromObj[key] !== 'object'){ // 是否為對象
toObj[key] = fromObj[key] // 如果為普通值,則直接賦值
}else{
if(fromObj[key] === null){
toObj[key] = null
}else{
toObj[key] = new fromObj[key].constructor // 如果為object强窖,則new這個object指向的構(gòu)造函數(shù)
deepCopy(fromObj[key],toObj[key]) // 遞歸
}
}
}
return toObj
}
let dog = {
name:"小白",
sex:"公",
firends:[
{
name:"小黃",
sex:"母"
}
]
}
let dogcopy = deepCopy(dog)
// 此時我們把dog的屬性進(jìn)行增加
dog.firends.push({name:"小紅",sex:"母"})
console.log(dog) // { name: '小白',
sex: '公',
firends: [ { name: '小黃', sex: '母' }, { name: '小紅', sex: '母' } ] }
// 當(dāng)我們打印dogcopy凸椿,會發(fā)現(xiàn)dogcopy不會受dog的影響
console.log(dogcopy) // { name: '小白',
sex: '公',
firends: [ { name: '小黃', sex: '母' } ] }
方法三
let dog = {
name:"小白",
sex:"公",
firends:[
{
name:"小黃",
sex:"母"
}
]
}
function deepCopy(obj) {
if(obj === null) return null
if(typeof obj !== 'object') return obj
if(obj instanceof RegExp) return new RegExp(obj)
if(obj instanceof Date) return new Date(obj)
let newObj = new obj.constructor
for(let key in obj){
newObj[key] = deepCopy(obj[key])
}
return newObj
}
let dogcopy = deepCopy(dog)
dog.firends.push({name:"小紅",sex:"母"})
console.log(dogcopy)