js继承与原型链

JavaScript语言的继承机制没有“子类”和“父类”的概念,也没有“类”(class)和“实例”(instance)的区分,全靠一种很神奇的原型链(prototype chain)模式,来实现继承。
c++和Java使用new命令时,都会调用“类”的构造函数(constructor)。在JavaScript中,new命令后面跟的不是类,而是构造函数。
举例来说,现在有一个DOG的构造函数,表示狗对象的原型:

function DOG(name) {
    this.name = name;
}

对这个构造函数使用new,就会生成一个狗对象的实例。

var dogA = new DOG('大毛')alert(dogA.name); // 大毛

主义构造函数中的this关键字,就代表了新创建的实例对象。

new的缺点

用构造函数生成实例对象,有一个缺点,就是无法共享属性和方法。

function DOG(name) {
    this.name = name;
    this.species = '犬科';
}
// 生成两个实例对象
var dogA = new DOG('大毛');
var dogB = new DOG('二毛');
// 这两个对象的species属性是独立的,修改其中一个,不会影响到另一个
dogA.species = '猫科';
alert(dogB.species); // 犬科,不收dogA的影响

因此,每个实例对象都有自己的属性和方法的副本,这不仅无法做到数据共享,也极大的浪费资源。

prototype属性的引入

prototype属性包含一个对象(以下简称“prototype对象”),所有的实例对象需要共享的属性和方法都放在这个对象里面,那些不需要共享的属性和方法就放在构造函数里面。
实例对象一旦创建,将自动引用prototype对象的属性和方法,即实例对象的属性和方法分成两种,一种是本地的,另一种是引用的。

function DOG(name) {
    this.name = name;
}
DOG.prototype = { species: '犬科' };

// 生成两个实例对象
var dogA = new DOG('大毛');
var dogB = new DOG('二毛')alert(dogA.species); // 犬科
alert(dogB.species); // 犬科

// 因为species属性放在prototype对象里,所以是两个对象共享的,只要修改了,就会影响到两个实例对象
DOG.prototype.species = '猫科';
alert(dogA.species); // 猫科
alert(dogB.species); // 猫科

使用不同的方法来创建对象和生成原型链

var o = { a : 1 };
o这个对象继承了object.prototype上面的所有属性
o自身没有名为hasOwnPrototype的属性
hasOwnPrototype是Object.prototype的属性
因此o继承了Object.prototype的hasOwnPrototype
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

prototype和Object.getPrototypeOf

var a1 = new A();
var a2 = new A();

那么a1.doSomething事实上会指向Object.getPrototypeOf(a1).doSomething, 就是在A.prototype.doSomething中定义的内容,即:
Object.getPrototypeOf(a1).doSomething == Object.getPrototypeOf(a2).doSomething == A.prototype.doSomething.

所以,当执行:var o = new Foo();
JavaScript实际上执行的是:

var o = new Object();
o._proto_ = Foo.prototype;
Foo.call(o);

然后当执行:o.someProp;
它检查 o 是否具有 someProp 属性。如果没有,它会查找 Object.getPrototypeOf(o).someProp,如果仍旧没有,它会继续查找 Object.getPrototypeOf(Object.getPrototypeOf(o)).someProp。

参考
Javascript继承机制的设计思想
继承与原型链

你可能感兴趣的:(js,js,继承,原型链,prototype)