js实现继承的几种方式?extends用的是哪种继承

1. 原型链式继承

缺点:由于俩个实例使用的是同一个原型对象,他们的内存空间是共享的,当其中一个变化时,另一个也跟着变化

function Parent() {
    this.name = 'parent'
    this.number = [1,2,3]
}
Parent.prototype.getName = function() {
    return this.name  // parent
}

function Child() {
    this.newName = 'child'
}
Child.prototype = new Parent()
console.log(new Child())

2.构造函数继承(Parent.call(this))

缺点:父类原型对象中存在父类之前自己定义的方法,子类将无法继承这些方法

function Parent() {
    this.name = 'parent'
}
Parent.prototype.getName = function() {
    return this.name
}
let parent = new Parent()
console.log('getName-Parent:',parent.getName())

function Child() {
    Parent.call(this)  // 改变this指向,this是 Child函数
    this.newName = 'child'
}
let child = new Child()
console.log('child:',child)
console.log('getName:',child.getName)

 

3.组合式继承 

缺点: Parent执行了俩次, 第一次是改变Child的prototype的时候, 第二次是通过call方法调用Parent,Parent多构造一次就多进行了一次性能开销

function Parent() {
    this.name = 'parent'
    this.number = [1,2,3]
}
Parent.prototype.getName = function() {
    return this.name
}

function Child() {
    // 第二次调用Parent()
    Parent.call(this) // 改变this指向
    this.newName = 'child'
}
// 第一次调用 Parent()
Child.prototype = new Parent()
// 手动挂上构造器,指向自己的构造函数
Child.prototype.constructor = Child

var child1 = new Child()
var child2 = new Child()
child1.number.push(4)
console.log(child1.number, child2.number) // 不互相影响 [1,2,3,4] [1,2,3]
console.log(child1.getName()) // 'parent'
console.log(child1.getName()) //  parent

4.原型继承:拷贝继承(Object.create()),这个方法接收俩个参数:一个是用作新对象原型的对象,而是新对象定义额外的对象,实现的是浅拷贝

缺点:多个实例的引用类型属性指向相同的内存地址,存在篡改的可能

let parent =  {
    name: 'parent',
    number: [1,2,3],
    getName: function() {
        return this.name
    }
}

let child1 = Object.create(parent)
child1.name = 'child1'
child1.number.push(4)

let child2 = Object.create(parent)
child2.number.push(5)

console.log(child1.name) // child1
console.log(child1.name === child1.getName()) // true

console.log(child2.name) // parent
console.log(child1.number) // [1,2,3,4,5]
console.log(child2.number) // [1,2,3,4,5]

5.寄生式继承

在原型继承的基础上,再添加一些方法,进行返回

缺点:同原型继承

let parent =  {
    name: 'parent',
    number: [1,2,3],
    getName: function() {
        return this.name
    }
}

function clone(original) {
    let clone = Object.create(original)
    clone.getNumber = function() {
        return this.number
    }
    return clone
}

let child = clone(Parent)
console.log(child.getName()) // parent
console.log(child.getNumber()) // [1,2,3]

6.寄生组合式继承

extends基本和寄生组合式继承类似


function Parent() {
    this.name: 'parent'
    this.number: [1,2,3]
}

Parent.prototype.getName = function() {
    return this.name
}

function Child() {
    Parent.call(this)
    this.newName = 'child'
}


function clone(parent, child) {
    // 这里改用 Object.create 就可以减少组合继承中多进行一次构造的过程
    child.prototype = Object.create(parent.prototype)
    child.prototype.constructor = child
}
clone(Parent, Child)

Child.prototype.getNewName = function() {
    return this.newName
}

let child = new Child()
console.log(child)
console.log(child.getName()) // parent
console.log(child.getNewName()) // child

示例

const foo = function(a) {
    console.log('this:',this)
    this.name = 'foo'
    this.a = 'aa'
    this.fun = function() {
        console.log('baz:',this.a) // aa
        console.log('baz:',a) // 3
    }
    function b() {
        console.log('b:', a) 
    }
}

foo.prototype = {
    c: function() {
        console.log('this.name',this.name) // foo
        console.log('c:', a) // a is not defined
    }
}

const f = new foo(3)

console.log('f:',f)
f.fun() // 3
f.c() // this.name: foo  a is not defined
f.b() // f.b is not a function



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值