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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章