1. 程式人生 > >js 中的物件拷貝

js 中的物件拷貝

js 中物件的拷貝很常見,特別是在面試中很常見

一: 物件淺拷貝與深拷貝和物件引用的區別

var a= {name:'anikin'}
var b = jsons
a == b  // true
b.name == 'jack'
a.name  // 'jack'

上述程式碼中,使用了=進行賦值,於是b指向了a所指向的棧的物件,也就是ab指向了同一個棧物件,所以在對b.name賦值時,a.name也發生了變化。

為了避免上面的情況,可以對物件進行拷貝,程式碼如下:

var a = {name:'wanger'}
var b = Object.assign({}, a)
a===b // false
b.name = 'zhangsan' a.name //'wanger'

上面程式碼將原始物件拷貝到一個空物件,就得到了原始物件的克隆,這時候a與b指向的是不同的棧物件,所以對b.name重新複製也不會影響到a.name。

但是如果a.name是一個物件的引用,而不是一個字串,那麼上面的程式碼也會遇到一些問題,參考如下程式碼:

var a = {name:{firstName:'wang',lastName:'er'}}
var b = Object.assign({}, a)
a===b // false
b.name.firstName = 'zhang'
a.name.firstName //'zhang'

b.name.firstName又影響到了a.name.firstName,這是因為Object.assign()方法只是淺層拷貝,a.name是一個棧物件的引用,賦值給b時,b.name也同樣是這個棧物件的引用,很多時候,我們不想讓這種事情發生,所以我們就需要用到物件的深拷貝。

二、使用JSON.parse()與JSON.stringify()對物件進行拷貝

 var b = JSON.parse(JSON.stringify(a))

這種方法只適用於純資料json物件的深度克隆,因為有些時候,這種方法也有缺陷,參考如下程式碼:

var clone = function (obj)
{
return JSON.parse(JSON.stringify(obj)); } var a = { a:function(){console.log('hello world')}, b:{c:1}, c:[1,2,3], d:"wanger", e:new Date(), f:null, g:undefined } var b = clone(a)

這裡寫圖片描述
我們發現,上述的方法會忽略值為function以及undefied的欄位,而且對date型別的支援也不太友好。

更要緊的是,上述方法只能克隆原始物件自身的值,不能克隆它繼承的值。 因此在用這個方法的時候小心使用。

三, 一般寫法

    function myextends(t,c){  //用後面的覆蓋前面的 
       var t = t||{};
       for( var attr in c ){
        if( c.hasOwnProperty(attr) ){

             if( typeof c[attr]  == 'object'){
                  //console.log(c[attr],c[attr].Contructor )
                 t[attr] = (c[attr].constructor === Array)?[]:{}
                 arguments.callee(t[attr],c[attr])

             }else{
                 t[attr] = c[attr]
             }

        }
     }
     return t
  }