欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript對象拷貝與Object.assign用法實例分析

 更新時間:2018年06月20日 10:13:05   作者:憶之逸之  
這篇文章主要介紹了JavaScript對象拷貝與Object.assign用法,結合實例形式分析了javascript深拷貝與淺拷貝以及Object.assign的功能與相關使用技巧,需要的朋友可以參考下

本文實例講述了JavaScript對象拷貝與Object.assign用法。分享給大家供大家參考,具體如下:

深拷貝與淺拷貝

在 JavaScript 中,對于基本數(shù)據(jù)類型(undefined、null、boolean、number、string)來說,在變量中存儲的就是這個變量本身的值,復制是對值的復制,不存在深淺之說。但C系語言的共同特點中有,存儲引用類型(對象),實際中在變量里存的是它的地址。因此對 JavaScript 中的復雜數(shù)據(jù)類型(object)來說,也會有淺拷貝和深拷貝的概念:淺拷貝指兩個不同的變量存的是同一個對象的地址,即兩個變量指向同一塊內(nèi)存區(qū)域;深拷貝則是重新分配了一塊內(nèi)存區(qū)域來存儲復制后的對象,兩個變量存的是真正的兩個互不影響的變量。

p.s. 有些資料認為淺拷貝是重新分配內(nèi)存,并把原對象中的各個屬性進行依次復制而不進行遞歸復制屬性值是對象的情況,也就是只復制對象的最外面一層。本文將這種情況歸于“深拷貝和淺拷貝的中間情況”,文中以“是否劃分新的內(nèi)存”為界限劃分深淺拷貝,這種劃分方式與 C/C++、C#、Java 等C系語言保持概念一致。

淺拷貝在JavaScript中的實現(xiàn)

淺拷貝在js中很簡單,例如:

let objA = {
  name: '對象A',
  content: '我是A'
};
let copyA = objA;
console.log(objA.name); // ==> "對象A"
console.log(copyA.name); // ==> "對象A"

如此即得到了objA的一份淺拷貝copyA,由于指向的是同一個對象,因此在修改objA的同時也是修改了copyA,反之亦然。

Object.assign()

Object.assign(target, …sources) MDN上對該方法的描述是 將所有可枚舉屬性的值從一個或多個源對象復制到目標對象,String類型和 Symbol 類型的屬性都會被拷貝, 并且該方法會忽略值為 或者 undefined 的源對象。例如:

var o1 = { a: 1 };
var o2 = { [Symbol('foo')]: 2 };
var obj = Object.assign({}, o1, o2);
console.log(obj); // { a : 1, [Symbol("foo")]: 2 } (cf. bug 1207182 on Firefox)
Object.getOwnPropertySymbols(obj); // [Symbol(foo)]

Object.assign 的深拷貝與淺拷貝

注意前面說的是可枚舉屬性,這是一個介于完全的深拷貝和完全的淺拷貝之間的方法:如果我們把它的第一個參數(shù)target設置為一個空對象 {},同時保證剩余的源對象sources中的屬性類型不包含引用類型,則該方法的返回值就是一個與源對象相同的但并不在同一塊內(nèi)存空間另一個對象,即獲得了源對象的深拷貝。但是,如果源對象的屬性中包含某個對象,也就是這個屬性的值指向某個對象,就像下面這樣:

var obj = {
  name: 'obj name',
  content: {
    a: 1,
    b: 2
  }
};

則使用 Object.assign({}, obj) 時,返回的目標對象中的content屬性與源對象obj中的content屬性指向的同一塊內(nèi)存區(qū)域,即對obj下的content屬性進行了淺拷貝。因此針對深拷貝,需要使用其他方法,比如自己實現(xiàn)一個深拷貝的方法,或者使用 JSON.parse(JSON.stringify(obj)), 因為 Object.assign()拷貝的是屬性值。

Object.assign 的屬性覆蓋

如果目標對象中的屬性具有相同的鍵,則屬性將被源中的屬性覆蓋。后來的源的屬性將類似地覆蓋早先的屬性,因此可以用來合并對象(常用的一個場景是使用reducers更新React應用的狀態(tài))。

var o1 = { a: 1, b: 1, c: 1 };
var o2 = { b: 2, c: 2 };
var o3 = { c: 3 };
var obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }

關于對象的繼承屬性和不可枚舉屬性

前文有提到,Object.assign 拷貝的是對象的可枚舉屬性,該方法使用源對象的 [[Get]] 和目標對象的 [[Set]],所以它會調用相關 getter setter。因此,不如說它是分配屬性,而不僅僅是復制或定義新的屬性。如果合并源包含 getter,這可能使其不適合將新屬性合并到原型中,將屬性定義(包括其可枚舉性)復制到原型應使用Object.getOwnPropertyDescriptor()Object.defineProperty() ,因此 Object.assign 不能拷貝對象的繼承屬性,例如:

var obj = Object.create({foo: 1}, { // foo 是個繼承屬性。
  bar: {
    value: 2 // bar 是個不可枚舉屬性。
  },
  baz: {
    value: 3,
    enumerable: true // baz 是個自身可枚舉屬性。
  }
});
var copy = Object.assign({}, obj);
console.log(copy); // { baz: 3 }

當源對象是原始數(shù)據(jù)類型時

ECMAScript 有 5 種原始類型(primitive type): UndefinedNull、BooleanNumber String。當Object.assign的源對象是原始類型時,源對象會被包裝成“對象”,對應的鍵是它在源對象中的索引值:

var v1 = "abc";
var v2 = true;
var v3 = 10;
var v4 = Symbol("foo")
var obj = Object.assign({}, v1, null, v2, undefined, v3, v4); 
// 原始類型會被包裝,null 和 undefined 會被忽略。
// 注意,只有字符串的包裝對象才可能有自身可枚舉屬性。
console.log(obj); // { "0": "a", "1": "b", "2": "c" }

當拷貝過程中發(fā)生異常時

在出現(xiàn)錯誤的情況下,例如,如果屬性不可寫,會引發(fā)TypeError,異常會打斷后續(xù)的拷貝任務。如果在引發(fā)錯誤之前添加了任何屬性,則可以更改target對象。

var target = Object.defineProperty({}, "foo", {
  value: 1,
  writable: false
}); // target 的 foo 屬性是個只讀屬性。
Object.assign(target, {bar: 2}, {foo2: 3, foo: 3, foo3: 3}, {baz: 4});
// TypeError: "foo" is read-only
// 注意這個異常是在拷貝第二個源對象的第二個屬性時發(fā)生的。
console.log(target.bar); // 2,說明第一個源對象拷貝成功了。
console.log(target.foo2); // 3,說明第二個源對象的第一個屬性也拷貝成功了。
console.log(target.foo); // 1,只讀屬性不能被覆蓋,所以第二個源對象的第二個屬性拷貝失敗了。
console.log(target.foo3); // undefined,異常之后 assign 方法就退出了,第三個屬性是不會被拷貝到的。
console.log(target.baz); // undefined,第三個源對象更是不會被拷貝到的。

更多關于JavaScript相關內(nèi)容感興趣的讀者可查看本站專題:《javascript面向對象入門教程》、《JavaScript錯誤與調試技巧總結》、《JavaScript數(shù)據(jù)結構與算法技巧總結》、《JavaScript遍歷算法與技巧總結》及《JavaScript數(shù)學運算用法總結

希望本文所述對大家JavaScript程序設計有所幫助。

相關文章

  • 可以將word轉成html的js代碼

    可以將word轉成html的js代碼

    這段很短的代碼,可以將word轉出html格式的代碼,當然word自己也帶的,另存為里面就有的,喜歡的朋友可以試試。
    2010-04-04
  • p5.js入門教程之圖片加載

    p5.js入門教程之圖片加載

    這篇文章主要介紹了p5.js入門教程之圖片加載,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • JavaScript 動態(tài)加載腳本和樣式的方法

    JavaScript 動態(tài)加載腳本和樣式的方法

    這篇文章主要介紹了JavaScript 動態(tài)加載腳本和樣式的方法,需要的朋友可以參考下
    2015-04-04
  • JAVA四種基本排序方法實例總結

    JAVA四種基本排序方法實例總結

    這篇文章主要介紹了JAVA四種基本排序方法,較為詳細的總結分析了插入法、冒泡法、選擇法及Shell排序等四種常用的排序技巧,非常具有實用價值,需要的朋友可以參考下
    2015-07-07
  • Javascript之this關鍵字深入解析

    Javascript之this關鍵字深入解析

    如我之前的文章所述(Javascript作用域),定義在全局的函數(shù),函數(shù)的所有者就是當前頁面,也就是window對象
    2013-11-11
  • 如何使用JavaScript計算SHA-256?hash值詳解

    如何使用JavaScript計算SHA-256?hash值詳解

    SHA-256是一種常用的散列函數(shù),廣泛應用于多種安全程序和協(xié)議中,如TLS、SSL、SSH、PGP和比特幣等,在JavaScript中,可以通過原生API輕松計算SHA-256的hash值,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-10-10
  • 盤點7個簡單但棘手的JavaScript面試問題分析

    盤點7個簡單但棘手的JavaScript面試問題分析

    這篇文章主要為大家介紹了盤點7個簡單但棘手的JavaScript面試問題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-11-11
  • 怎么使用js計算當前一周的日期

    怎么使用js計算當前一周的日期

    這篇文章主要給大家介紹了關于怎么使用js計算當前一周的日期的相關資料,我們可以使用JavaScript的Date對象來獲取近一周的日期,文中給出了詳細的代碼示例,需要的朋友可以參考下
    2023-09-09
  • JavaScript語言中的Literal Syntax特性分析

    JavaScript語言中的Literal Syntax特性分析

    JavaScript語言中的Literal Syntax特性分析...
    2007-03-03
  • js中setTimeout的妙用--防止循環(huán)超時

    js中setTimeout的妙用--防止循環(huán)超時

    本文主要介紹了使用setTimeout實現(xiàn)防止循環(huán)超時的方法,具有很好的參考價值。下面跟著小編一起來看下吧
    2017-03-03

最新評論