继承和原型链

继承方面,JavaScript 中的每一个对象都有一个内部私有的连接指向另外一个对象,这个对象就是原对象的原型。这个原型对象也有本身的原型,直到对象的原型为 null 为止(也就是没有原型)。这种一级一级的链结构就称为原型链数组

虽然这一般会被称做 JavaScript 的弱点之一,实际上这种原型继承的模型要比经典的继承模型还要强大。虽然在原型模型上构建一个经典模型是至关琐碎的,但若是采起其余方式实现则会更加困难。函数

基于原型链的继承

继承属性

JavaScript 对象有两种不一样的属性,一种是对象自身的属性,另一种是继承于原型链上的属性。下面的代码则演示了当访问一个对象的属性时发生的行为:this

// 假定咱们有个对象o,而且o所在的原型链以下:
// {a:1, b:2} ---> {b:3, c:4} ---> null
// 'a'和'b'是o自身的属性.

// 该例中,用"对象.[[Prototype]]"来表示这个对象的原型.
// 这只是一个纯粹的符号表示(ECMAScript标准中也这样使用),不能在实际代码中使用.

console.log(o.a); // 1
// a是o的自身属性吗?是的,该属性的值为1

console.log(o.b); // 2
// b是o的自身属性吗?是的,该属性的值为2
// o.[[Prototype]]上还有一个'b'属性,可是它不会被访问到.这种状况称为"属性遮蔽".

console.log(o.c); // 4
// c是o的自身属性吗?不是,那看看o.[[Prototype]]上有没有.
// c是o.[[Prototype]]的自身属性吗?是的,该属性的值为4
console.log(o.d); // undefined
// d是o的自身属性吗?不是,那看看o.[[Prototype]]上有没有.
// d是o.[[Prototype]]的自身属性吗?不是,那看看o.[[Prototype]].[[Prototype]]上有没有.
// o.[[Prototype]].[[Prototype]]为null,原型链已到顶端,没有d属性,返回undefined

 

继承方法

JavaScript 并无真正的“方法”,JavaScript 只有函数,并且任何函数均可以添加到对象上做为对象的属性。继承的函数与其余的属性是基本没有差异的,包括“属性遮蔽”(这种状况至关于其余语言的方法重写)。prototype

当继承的函数被调用时,this 指向的是当前继承原型的对象,而不是继承的函数所在的原型对象。code

var o = {
  a: 2,
  m: function(){
    return this.a + 1;
  }
};

console.log(o.m()); // 3
// 当调用 o.m 时,'this'指向了o.

var p = Object.create(o);
// p是一个对象, p.[[Prototype]]是o.

p.a = 12; // 建立p的自身属性a.
console.log(p.m()); // 13
// 调用p.m时, 'this'指向 p. 'this.a'则是12.1

 

使用不一样的方法来建立对象和生成原型链

使用普通语法建立对象

var o = {a: 1};

// o这个对象继承了Object.prototype上面的全部属性
// 因此能够这样使用 o.hasOwnProperty('a').
// hasOwnProperty 是Object.prototype的自身属性。
// Object.prototype的原型为null。
// 原型链以下:
// o ---> Object.prototype ---> null

var a = ["yo", "whadup", "?"];

// 数组都继承于Array.prototype (indexOf, forEach等方法都是从它继承而来).
// 原型链以下:
// a ---> Array.prototype ---> Object.prototype ---> null

function f(){
  return 2;
}

// 函数都继承于Function.prototype(call, bind等方法都是从它继承而来):
// f ---> Function.prototype ---> Object.prototype ---> null
相关文章
相关标签/搜索