Skip to content

原型链与继承浅谈 #5

@jmx164491960

Description

@jmx164491960

创建对象有几种方法

// 第一种
var o1 = {
    name: 'o1'
}
// 第二种
var o2 = new Object({
    name: 'o2'
});
// 第三种
var createFn = function() {
    this.name = 'o3'
}
// 第四种
var o3 = new createFn()
var temp = {
    name: 'o4'
}
// 第五种 Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
var o4 = Object.create(temp)

上面的创建方式中,只有第三种有构造函数,o3.constructor === createFn。

原型、构造函数、实例、原型链

image

举一个例子:

function creator() {
    this.name = 'son';
}
creator.prototype.parent = 'parent';
let c = new creator();

c是实例,实例的原型对象是c.proto
构造函数creator,creator.prototype === c.proto

实现继承的几种方式

以下会列出不同种类实现方式的继承,从简陋的继承到最完美的继承。

构造函数

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

原型链

1.相比构造函数各有利弊,利是少执行了一个父类的构造函数,弊是Child生成的实例没有parent属性,需要靠原型链查找,即多个实例同用一个父类属性。

function Parent() {
    this.parent = 'parent'
}
function Child() {
    this.name = 'child'
}
Child.prototype = new Parent()

2.改进:相比上一个,Child生成的每个实例拥有了自己的parent属性。

function Parent() {
    this.parent = 'parent'
}
function Child() {
    Parent.call(this)
    this.name = 'child'
}
Child.prototype = new Parent()

3.改进:相比上一个,在new一个实例的时候。少执行了一次Parent实例构造函数的执行。

function Parent() {
    this.parent = 'parent'
}
function Child() {
    Parent.call(this)
    this.name = 'child'
}
Child.prototype = Parent.prototype

4.这种几乎是原型链最完美的继承
改进:相比上一个,实例的__proto__的constructor,并且Child和Parent不再引用同一条原型链。

function Parent() {
    this.parent = 'parent'
}
function Child() {
    Parent.call(this)
    this.name = 'child'
}
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child

修改了constructor这样用instanceof区分究竟是用Child构造函数生成的还是Parent构造函数生成的

ES6写法

class Parent {
    constructor() {
        this.parent = 'parent'
    }
}

class Child extends Parent {
    constructor() {
        super()
        this.name = 'child'
    }
}
let p = new Parent()
let c = new Child()

这种写法和原型链里最后一种,原理一致。但是写法更简单。如果不需要考虑ES6以下的兼容的话,推荐该写法

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions