我的博客
  • JavaScript原型链学习

JavaScript原型链学习

prototype VS __prop__

JavaScript通过原型链的方式实现复用。在对象实例中,有一个特殊的属性__prop__,它指向的是它的原型。当我们使用构造函数来创建一个对象的时候,这个构造函数存在一个prototype属性,这个属性指向同构造函数创建出来的对象的__prop__相同。

例如

function Animal(name) {
    this.name = name
    this.makeNoise = () => {
        console.log('...')        
    }
    this.introduce = function(){
        console.log(`I am ${this.name}`)
    }
}

上边这个构造函数创建的对象的__prop__同Animal.prototype指向相同的对象。但是我们一般不直接使用obj.__prop__来得到该对象的原型,而是使用Object.getPrototypeOf(obj)

let animal = new Animal('animal')
console.assert(Object.getPrototypeOf(animal) === Animal.prototype);

用call方法实现继承

用call方法,也就是使用this在运行时绑定的特性,在this中创建父类的属性和方法

function Dog(species) {
    this.species = species
    Animal.call(this, 'dog')
    this.makeNoise = () => {
        console.log('wuff')
    }
}

但是这样做的话,Dog的创建的对象其实原型并不是Animal

用Object.create()实现继承

为了弥补缺点,我们在继承的构造函数中把this的原型替换成父类的一个实例。

function Animal(name) {
    this.name = name
    this.makeNoise = () => {
        console.log('...')        
    }
    this.introduce = function(){
        console.log(`I am ${this.name}`)
    }
}
function Dog(species) {
    Object.setPrototypeOf(this, new Animal('dog')) 
    this.species = species
    this.makeNoise = () => {
        console.log('wuff')
    }
    this.run = () => {
        console.log('run')
    }
}

关于继承网上有很多实现方式,但是es6已经规范了语法,用class和extends关键字可以实现原型链的继承。 如下写法

class Subject {
    constructor() {

    }   
}

class Math extends Subject {
    constructor() {
        super()
    }
}

let math = new Math()
console.log(math instanceof Subject)

如果不想使用es6提供的语法糖,官方也有Object.create()来实现继承。Object.create()可以在MDN搜索到用法。

最近更新: 2026/3/15 14:17
Contributors: Keyang Li