JS中的对象之原型

对象

 

ECMAScript做为一个高度抽象的面向对象语言,是通过_对象_来交互的。即使ECMAScript里边也有_基本类型_,但是,当需要的时候,它们也会被转换成对象。

一个对象就是一个属性集合,并拥有一个独立的prototype(原型)对象。这个prototype可以是一个对象或者null。

var foo={
  x: 10,
  y:20
};

我们拥有一个这样的结构,两个明显的自身属性和一个隐含的_proto_属性,这个属性

是对foo原型对象的引用:

这些prototype有什么用?让我们以_原型链_(prototype chain)的概念来回答这个问题。

 

原型链

原型对象也是简单的对象并且可以拥有它们自己的原型。如果一个原型对象的原型是一个非null的引用,那么以此类推,这就叫作_原型链_。

原型链是一个用来实现继承和共享属性的有限对象链。

ECMAScript中没有类的概念。但是,代码重用的风格并没有太多不同(尽管从某些方面来说比基于类(class-based)的方式要更加灵活)并且通过_原型链_来实现。这种继承方式叫作_委托继承_(delegation based inheritance)(或者,更贴近ECMAScript一些,叫作_原型继承_(prototype based inheritance))。

var a = {
  x: 10,
  calculate: function(z) {
    return this.x + this.y;
  }
} ;

var b = {
  y:20,
  _proto_:a
};

var c = {
  y: 30,
  _proto_:a
}

// call the inherited method

b.calculate(30);  //60
c.calculate(40);  //80


这样我们通过将a作为一个属性值赋值给b, c的_proto_属性;

足够简单,这就是通过原型链实现的。

看看规则:如果一个属性或者方法在_自身_中无法找到(也就是说是对象自身没有一个那样的属性),然后他就会尝试在原型链中寻找这个属性/方法。如果这个属性没有在原型中找到,那么将会查找这个原型的原型,以此类推,遍历整个原型链(当然这在类继承中也是一样的,当解析一个继承的_方法_的时候-我们遍历_class链_( class chain))。第一个被查找到的同名属性/方法会被使用。因此,一个被查找到的属性叫作_继承_属性。如果在遍历了整个原型链之后还是没有查找到这个属性的话,返回undefined值。

注意,继承方法中所使用的this的值被设置为_原始_对象,而并不是在其中查找到这个方法的(原型)对象。也就是,在上面的例子中this.y取的是bc中的值,而不是a中的值。但是,this.x是取的是a中的值,并且又一次通过_原型链_机制完成。

如果没有明确为一个对象指定原型,那么它将会使用__proto__的默认值-Object.prototypeObject.prototype对象自身也有一个__proto__属性,这是原型链的_终点_并且值为null

 

posted @ 2017-07-12 14:17  wangyong1992  阅读(856)  评论(0编辑  收藏  举报