javascript进阶学习:关于原型和原型链的土话讲解,以及如何基于原型链实现继承

蛰伏已久 蛰伏已久 2019-01-24

原型和原型链是js实现继承的一个重要特性,也可能是面试必问的问题,有很多这方面的讲解,但是都太让人费劲,小编试着用简单的语言来描述出来

本文我们的目标就是理解什么是原型链,以及如何通过原型链来实现类的继承

类的实现

假如我们要实现一个Animal类,我们会怎么做呢?很简单,相信大家都知道,如下

function Animal() {

}

Animal.prototype.eat=function () {
    console.log("作为动物,我必须要学会进食")
}

Animal.prototype.run=function () {
    console.log("作为动物,我必须要学会跑")
}

var dog=new Animal()

dog.eat()
dog.run()

函数Animal 我们称为构造函数

这个构造函数的属性prototype,我们称为原型或原型对象(实际就是一个普通对象)

一个类我们可以看做由这两部分构成,构造函数和原型对象

变量dog是类的1个实例,拥有类的原型对象的属性(一些值和一些方法)

接下来,我们把dog打印出来,看看都有什么。这块不重要,了解就好,不要有压力

console.log(dog)
//显示dog拥有该属性 __proto__

我们发现dog这个实例拥有一个__proto__属性,而且这个__proto__属性等于类的原型对象

也就是说实例的__proto__属性指向这个实例所属类的原型对象prototype

console.log(dog.__proto__===Animal.prototype)  //true

我们再把Animal.prototype原型对象打印出来看看都有什么

console.log(Animal.prototype)

//eat: ƒ ()
//run: ƒ ()
//constructor: ƒ Animal()
//__proto__: Object

可以看到除了我们自定义的eat和run方法外,还有一个constructor属性,指向构造函数,原型对象也有一个__proto__属性,实际每个对象都有

结论:默认情况下类的原型对象拥有一个constructor属性,指向构造函数

console.log(Animal.prototype.constructor===Animal)

简单点,我们知道一个类由构造函数和原型对象构成就好了,类的实例会从原型对象那里继承一些属性和方法

那怎么实现继承呢?如果子类的原型对象,能够从父类那里复制过来一些属性,不就完成了继承吗

类的继承

我们再添加一个Dog类,期望它能够继承Animal类,

function Animal() {

}

Animal.prototype.eat=function () {
    console.log("作为动物,我必须要学会进食")
}

Animal.prototype.run=function () {
    console.log("作为动物,我必须要学会跑")
}


//新增Dog的构造函数
function Dog() {

}
//Dog的原型对象先从Animal类那里复制一部分属性及方法,也就是对Animal类进行实例化
Dog.prototype=new Animal()
//上面的操作会把prototype.constructor给覆盖,所以手动更新一下
Dog.prototype.constructor=Dog
//为Dog对象添加自己的方法
Dog.prototype.say=function () {
    console.log("我说话就是汪汪汪")
}

var jinmao=new Dog()
//Dog实例拥有以下3个方法,实现了继承
jinmao.eat()
jinmao.run()
jinmao.say()

实现Dog继承于Animal,实际就是Dog的原型对象从Animal那里复制过来一部分属性和方法,也就是实例化一个Animal

这样Dog.prototype就拥有Animal的属性和方法了,Dog.prototype就是一个普通的对象,我们可以给它增加新的属性,比如上面增加了一个say属性,只是这个属性对应的是一个函数,我们称这个属性为方法,实际就是为原型对象增加一个属性

我们打印下面的值看看效果

console.log(jinmao.__proto__===Dog.prototype)  //true
console.log(Dog.prototype.__proto__===Animal.prototype) //true
console.log(Animal.prototype.__proto__===Object.prototype) //true,Animal的原型对象是一个普通对象,他继承于Object对象
console.log(Object.prototype.__proto__)   //null,Object.protype是最顶级的对象,他不继承于别的对象,因此为null

原型链

实例jinmao的__proto__指向子类Dog的原型对象

子类Dog的原型对象的__proto__又指向父类Animal的原型对象

Animal的原型对象是一个普通对象,它的__proto__指向Object的原型对象

Object的原型对象是顶级对象,其__proto__为null

__proto__属性就像一个链条一样,将实例、子类、父类、父类的父类.......连接起来,这应该就是原型链的直观意义了吧

以上就是关于原型链和继承的简单理解,为了方便理解,并没有举复杂的例子,希望能帮助大家理解核心概念

分享到

点赞(0)