Javascript對象賦值操做

首先,咱們仍是舉個例子來講明對象賦值操做的問題吧:
ps: 本文默認約定log = console.logjavascript

function A(){}
 A.prototype.x = 10;
 var a1 = new A();
 A.prototype = {
    x: 20,
    y: 20
 };
 var a2 = new A();
log([a1.x, a1.y, a2.x, a2.y]); // [10, undefined, 20, 20]

js中對象賦值操做咱們能夠經過c語言中得指針概念來解釋。java

對象的淺拷貝

直接經過賦值操做符「=」將變量a中的對象賦值給變量b,此時咱們更改a、b其中一個,另外一個也會隨之更改。數組

var a = [1, 1],
    b = a;
    b[0] = 2;
    log(a[0]); // 2

由於咱們在將a的對象賦值給b時,js引擎內部的操做只是簡單的將a所指的對象的地址賦值給b,此時a與b指向內存中同一個對象,因此纔會出現這種狀況。這種賦值方式稱爲對象的淺拷貝。
咱們能夠從另外一個方面論證咱們的觀點:prototype

log(a === b); // true,毫無疑問

var c = [2, 1];
log(a === c); // false

出現這種狀況的緣由就是變量c指向的是另外一個和變量a指向的對象的值相同的對象,僅僅只是兩個指向的對象的值相同,但兩個對象在內存的地址是不同的,因此是false。
另外,咱們知道js數組中有一些方法能夠實現數組的徹底複製,即兩個變量分別指向兩個對象:指針

b = a.concat([]),
    c = a.slice(0),
    d = a.splice(0, a.length);
    log(b === a); // false

可是咱們要針對對象進行復制的話,只能手動進行模擬,即所謂的對象深拷貝。code

對象的深拷貝

顧名思義,就是利用「=」對於基本類型的操做不存在上述問題,經過for-in深度遍歷對象的屬性,而後將其賦值給另外一個新的對象。對象

function cloneObj(obj) {
    var tempObj = {};
    
    if (obj instanceof Array) {
        tempObj = [];
    }
    
    for (var prop in obj) {
        if (typeof prop === 'Object') {
            cloneObj(prop);
        }
        
        tempObj[prop] = obj[prop];
    }
    
    return tempObj;
}

var myCountry = {
    name: 'China',
    birth: 1949
},

country = cloneObj(myCountry);

log(country === myCountry); // false

結束語

最後,咱們回到第一個例子,會發現,引擎內部對於new對象的原型鏈也是經過簡單的賦值操做的方式,即對象的淺拷貝。而ES5新增的Object.create()也是淺拷貝的一種封裝:ip

var myCountry = {
        name: 'China',
        birth: 1949
    },

    country = Object.create(myCountry);

console.log(country.__proto__ === myCountry); // true
相關文章
相關標籤/搜索