js中繼承(拷貝)的幾種常用方法

尋尋覓覓,尋尋覓覓,你終於找到了這兒。話不多說,直接開擼,我們先從最簡單的淺拷貝開始

淺拷貝:

這裏關於淺拷貝,我總結了三種方法,我們先來定義兩個對象

var person={
    name:"cj",
    age:'22',
    add:{
        c:"33",
        d:'44'
    }
}
var prog={
    lang:"javascript"
}

1、通過 for 循環來實現

function extend(p,c){
    var c=c || {};
    for(var prop in p){
        c[prop]=p[prop];
    }
}
extend(person,prog);

2.通過Object.assign實現淺拷貝

Object.assign(prog,person);

3.通過...擴展運算符來實現

prog={...person};

這種方式的繼承,缺點很明顯,就是當父對象中的屬性是一個對象或數組等之類的引用數據類型的時候,改變子也會改變父,因爲是對其的一個引用。

prog.add.c='66';    
console.log(person.add.c);  //66  ===>是對add的一個引用

深拷貝

1、遞歸調用

var person={
    name:"cj",
    age:'22',
    add:{
        c:"33",
        d:'44'
    }
}
var prog={
    lang:"javascript"
}

// 1.通過遞歸實現
function extend(p,c){
    var c=c || {};
    for(let i in p){
        if(typeof p[i]=='object'){
            c[i]=(p[i].constructor===Array) ? [] : {};  //這裏不考慮函數類型
            extend(p[i],c[i])
        }else{
            c[i]=p[i]
        }
    }
}
extend(person,prog)

2.通過 JSON.parse(JSON.stringify(object))來實現

var person={
    name:"cj",
    age:'22',
    add:{
        c:"33",
        d:'44',
        m:undefined
    }
}
var prog={
    lang:"javascript"
}
//1.Object.assign
Object.assign(prog,JSON.parse(JSON.stringify(person)))


//2.擴展運算符
prog={...JSON.parse(JSON.stringify(person))}

但是該方法也是有侷限性的:

  1. 會忽略 undefined
  2. 會忽略 symbol
  3. 不能序列化函數
  4. 不能解決循環引用的對象

其實實現一個深拷貝是很困難的,需要我們考慮好多種邊界情況(我們的遞歸方法就忽略了函數類型),比如原型鏈如何處理、DOM 如何處理等等,如果在開發中推薦使用 lodash 的深拷貝函數。

3、通過 lodash 的深拷貝函數來實現

const cloneDeep = require('loadsh/cloneDeep')
var person={
    name:"cj",
    age:'22',
    add:{
        c:"33",
        d:'44',
        m:undefined
    },
    val:function(){
        console.log('111')
    }
}
var prog={
    lang:"javascript"
}

prog = Object.assign(prog,cloneDeep(person))

下面我們來擴展一下:

函數式繼承

function Parent(){
    this.name='abc';
    this.age={
        ming:23
    }
}
function Child(){
    // Parent.bind(this)();  //bind調用之後是返回原函數,需要再調用一次才行
    Parent.call(this);
    // Parent.apply(this);
    this.add='jia'
}
var c=new Child()

原型鏈方式的繼承

var obj={
    name:"liuhua"
}

function extend(){
    var init={};
    function F(){};
    F.prototype=obj;  //原型對象的賦值一定要寫在實例化對象之前
    init=new F();
    return init;
}
var c=extend();
console.log(c.name)  //liuhua

ES5提供的Object.create(proto, [propertiesObject])   

  • proto:新創建對象的原型對象。
  • propertiesObject:

該方法創建一個新對象,使用現有的對象來提供新創建的對象的proto

var p={
    name:"dj"
}

var c=Object.create(p,{age:{value:100,enumerable:true}})  //這裏給c1增加屬性,必須通過這種規範添加,新添加的屬性默認不可枚舉
// console.log(c.name,c.age)
// console.log(c)  //{ age: 100 }

 

 

 

發佈了71 篇原創文章 · 獲贊 59 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章