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继承机制的设计思想
继承与原型链

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值