關於JS中的對象展開運算符“...”的一些思考

最近筆者在寫vue的時候用到了JS中的新特性展開運算符(ES6、ES7新提出)。展開運算符的加入可以使我們在寫JS代碼時更加簡潔靈活。可用於函數調用、解構賦值等方面。具體可以參考這篇博客:  ECMAScript 6學習筆記(一):展開運算符 。

今天筆者想說說對象展開運算符的使用,對象展開運算符提出於ES7的草案之中,可以這樣使用:

let shortcuts = {
    attr1: 3,
    attr2: 4
}
let shortcuts2 = {}
shortcuts2 = {...shortcuts}

上面的這種用法實際上相當於是:

shortcuts2 = {attr1: 3, attr2: 4}

這種寫法有好多好處,比如可以合併對象或者將一個對象插入另外一個對象中去:

let a = { x: 1, y: 2 }
let b = { z: 3 }
let ab = { ...a, ...b }
ab // { x: 1, y: 2, z: 3 }

以及與shortcuts2 = shortcuts這種直接引用賦值寫法的區別。我們知道對於引用類型來說賦值操作其實傳遞的只是這個對象的地址(粗淺的說),意味着如果按照shortcuts2 = shortcuts的寫法的話當改變shortcuts2中的屬性的值的話shortcuts也會同樣改變。換言之shortcuts和shortcuts2兩個變量指向了同一段內存地址。但是如果是 shortcuts2 = { ...shortcuts },這樣的寫的話,由於shortcuts中的屬性類型都是基本類型,相當於是新建了一個對象,此時改變shortcuts2中的屬性值,shortcuts將不受影響——某種意義上實現了對象之間的深拷貝,但是僅限於其屬性都爲基本類型的情況(或者說只進行了一層的深拷貝),如果該對象中的屬性還有引用類型的話,如下:

let obj1 = {
  attri1: [б, 6, 0],
  attri2: 4,
  attri4: 5
}
let obj2 = {...obj1}
console.log('obj2: ', obj2)
obj2.attri2 = 888 
obj2.attri1[0] = 7
// obj2.attri1 = [8, 8, 8, 8]
console.log('obj1:', obj1)
console.log('obj2:', obj2)

obj是一個既包含引用類型又包含基本類型屬性的對象,將其利用對象展開符賦值給obj2之後,修改obj2中的屬性值 

此時的輸出結果是這樣的:

 

obj2中的attri1數組中的第一個元素替換爲7之後,obj1中的attri1也收到了影響,但attri2是基本類型不受影響:說明對象展開運算符本質上是將obj1中的屬性按順序賦值給了obj2,此時基本類型進行的是值傳遞,而引用類型進行的是引用傳遞

因此在這種情況下要謹慎使用對象展開符,其和一般的引用傳遞過程有一定的區別。 

 

參考: http://www.cnblogs.com/mingjiezhang/p/5903026.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章