JS进阶系列之原型、原型链

最近在看 JavaScript忍者秘籍 这本书的时候,再加上最近遇到的关于原型、原型链的面试题,所以萌生了要把这些知识梳理一遍的想法,所以以下是我自己对原型、原型链的看法

什么是原型

提到原型,我们可能都会想到与对象有关的东西,但其实,原型是与函数才是密切相关的。每当我们创建一个函数,都会有一个指向该函数的原型对象的指针prototype,然后该原型对象上又有一个指向该函数的指针constructor,在这里,如果我们这个函数是一个构造函数,那么我们每实例化一个对象,该对象都会有一个指向该构造函数的原型对象的指针_proto_,那么我就以一个小的例子来讲解一下原型对象,构造函数与实例的关系。

function Ninja(){
   this.swung = true;
this.swingSword = function(){
     return !this.swung;
}
}
Ninja.prototype.swingSword = function(){
   return this.swung;
};
var ninja = new Ninja();

从图中可以看出,通过构造函数Ninja()创建了一个对象,并且这个对象的引用是一个变量ninja,然后该构造函数,又有一个指向它的原型对象的属性prototype


谈到原型,接下来就是原型对象的几个知识点。

  • 如果给对象实例添加了一个与原型对象中的某个同名属性,该对象实例上的这个属性会覆盖原型对象上的属性,我们可以通过代码来演示:
function Ninja(){
   this.swung = true;
this.swingSword = function(){
     return !this.swung;
}
}
Ninja.prototype.swingSword = function(){
   return this.swung;
};
var ninja = new Ninja();
ninja.swingSword();//false

因为每次访问实例中的属性是,都是一个向上查找的过程,会先从实例对象上查找有无这个属性,如果有,就返回这个属性,如果没有,就会继续往它的原型对象上找,一层层往上寻找,如果没有,就返回undefined。

  • 如果我们先实例化了一个对象实例,然后再改变了它的原型对象,这个改变会反映在这个对象实例上,因为原型对象上的改变会实时反应在每一个对象实例上,这也是原型对象的重要特性之一,代码演示实例如下:
function Ninja(){
   this.swung = true;
}
Ninja.prototype.swingSword = function(){
   return this.swung;
};
var ninja = new Ninja();
Ninja,prototype.swingSword = function(){
   return !this.swung;
}
ninja.swingSword();//false;

什么是原型链

原型链与javascript中的继承密切相关,可以说,继承是通过原型链来实现的。原型链可以理解为一个对象的实例是另一个对象的原型,然后另一个对象的实例又是另一个对象的原型,依次类推形成的一个链式结构
所以一般实现继承的方式是:将父类的实例作为子类的原型,用下面这个例子来讲解一下

function Person(){};
Person.prototype.dance = function(){};
function Ninja(){};
Ninja.prototype = new Person();
var ninja = new Ninja();

捕获2.PNG

从图片可以看出,让Person的一个实例作为子类Ninja对象的原型,这样,Ninja就继承了Person上的所有属性和方法,包括构造函数上的还有原型上的,这就是原型链实现继承的方法。
那么为什么我们不直接将父类的原型对象直接赋给子类的原型对象呢,那是因为如果我们这样做的话,对子类原型对象的改变,将会直接影响到了父类中的原型对象,这是一个不可取的方法。

posted @ 2017-04-29 15:49  McRay  阅读(285)  评论(0编辑  收藏  举报