13 对象 - 继承

许多 OO 语言都支持两种继承方式:接口继承实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。

由于JS函数没有签名,在 ECMAScript 中无法实现接口继承。 ECMAScript 只支持实现继承,而且其实现继承主要是依靠原型链来实现的。

1 继承的原理

继承是通过创建 SuperType 的实例,并将该实例赋给SubType.prototype 实现的。

function SuperType(){
    this.property = true;
}
SuperType.prototype.getSuperValue = function(){
    return this.property;
};
function SubType(){
    this.subproperty = false;
}
//继承了 SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function (){
    return this.subproperty;
};

var instance = new SubType();
alert(instance.getSuperValue()); //true

关系图如下:

拿上面的例子来说,调用instance.getSuperValue()会经历三个搜索步骤:

1)搜索实例;

2)搜索 SubType.prototype;

3)搜索 SuperType.prototype,最后一步才会找到该方法。

在找不到属性或方法的情况下,搜索过程总是要一环一环地前行到原型链末端才会停下来。

事实上,前面例子中展示的原型链还少一环。我们知道,所有引用类型默认都继承了 Object,而这个继承也是通过原型链实现的。

所以,完整的原型链应该如下:

由于原型链的关系,我们可以说 instance 是 Object、 SuperType 或 SubType 中任何一个类型的实例。

原型链虽然很强大,可以用它来实现继承,但它也存在一些问题。

主要是由于共享导致的。如下代码:

function SuperType(){
    this.colors = ["red", "blue", "green"];
}
function SubType(){
}

//继承了 SuperType
SubType.prototype = new SuperType();

var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
var instance2 = new SubType();
alert(instance2.colors); //"red,blue,green,black"

因为这种缺陷,实践中很少会单独使用原型链。

2 借用构造函数(经典继承)

function SuperType(){
    this.colors = ["red", "blue", "green"];
}
function SubType(){
    //继承了 SuperType
    SuperType.call(this);
}

var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
var instance2 = new SubType();
alert(instance2.colors); //"red,blue,green"

解读:

第一, new SubType()会创建一个新对象。

第二, SubType()中的this指向这个新对象。

第三, 在这个新对象中执行SuperType()函数,也相当于在这个新对象中运行SuperType()函数,也就给这个新对象加了一个属性colors数组。

第四, 将这个新对象名为为instance1。

这种方法的缺陷:方法都在构造函数中定义,因此函数复用就无从谈起了。考虑到这些问题,借用构造函数的技术也是很少单独使用的。

3 组合继承

指的是将原型链和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式。

function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
    alert(this.name);
};
function SubType(name, age){
    //继承属性
    SuperType.call(this, name);
    this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
    alert(this.age);
};

var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
instance1.sayName(); //"Nicholas";
instance1.sayAge(); //29

var instance2 = new SubType("Greg", 27);
alert(instance2.colors); //"red,blue,green"
instance2.sayName(); //"Greg";
instance2.sayAge(); //27

组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点,成为 JavaScript 中最常用的继承模式。

时间: 2024-10-01 23:55:44

13 对象 - 继承的相关文章

对象继承方式

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>对象继承</title> </head> <body> <script> /* function Person(name, age){ this.name = name; this.age = age; this.say

对象继承

说到面向对象继承就要扯到原型链了,因为ECMAScript实现继承的主要方法就是原型链,JavaScript高级程序设计一书中这样写到:继承基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法. 1.原型链继承 1 function Person(name,sex){ 2 this.name = name; 3 this.sex = sex; 4 } 5 Person.prototype.play = function(){ 6 console.log("running");

JS对象继承篇

JS对象继承篇 ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现的 原型链 其基本思路是利用原型让一个引用类型继承另一个引用类型的属性和方法 function Person(){ this.name = "Person"; } Person.prototype.getName = function(){ return this.name; }; function SuperPerson(name,sex){ this.name = name; this.sex

原型继承+原型链 + 对象继承发展

一.原型继承: 1.说起原型继承,就要先由构造函数创造对象说起,首先了解构造函数内部基本原理: (1).在函数体最前面隐式的加上this = {} (2).执行 this.xxx = xxx; (3).隐式的返回this 并且要注意隐士创建的this对象中有个名为__proto__的属性,其属性值为该构造函数继承的原型prototype. 而原型对象的有一个名为constructor的属性,其属性值为继承之的构造函数, 所以可以通过这两个属性相互查看 2.原型的定义及一些特点: a.定义:原型是

Python Special Syntax 13: 对象的字符串表示

repr函数和反引号用来获取对象的可打印的表示形式.你可以通过定义类的__repr__方法来控制你的对象在被repr函数调用的时候返回的内容. 在大多数时候有eval(repr(object)) == object. Let's start Python programming! 哇哈哈哈! 感谢:沈洁元 Swaroop C. H. Python Special Syntax 13: 对象的字符串表示

Javascript对象----继承

Javascript对象具有"自有属性",也有一些属性是从原型对象继承而来的.为了更好地理解这种继承,必须更深入地了解属性访问的细节. 假设要查询对象o的属性x,如果o中不存在x,那么将会在o的原型对象中查询属性x.如果原型对象中也没有x,但这个原型对象也有原型,那么会继续在这个原型对象的原型上执行查询,直到找到X或者查找到一个原型是null的对象位置.可以看到,对象的原型属性构成了一个"链",通过这个"链"可以实现属性的继承. var o = 

javaScript 工作必知(七) 对象继承

对象继承inherit var o = { r: 1 }; var c = function f() { }; c.prototype = o; c.r = 3; alert(o.r);//被继承的属性值未发生改变. alert(c.r);//c中r覆盖了o中的属性.     如何调用o中的r属性呢. var o = { r: 1 }; var c = function f() { }; c.prototype = o; alert(o.r);//1 被继承的属性值未发生改变. alert(c.

Python对象继承set类型

Python对象继承set类型 class Feature(set): def __init__(self): set.__init__(self) # 这里演示将Feature类的加号重载成set.add方法 def __add__(self, feature): set.add(self, feature)

学习Python的对象继承

Python是面向对象的语言,以下我对ConfigParaser.ConfigParaser对象的扩展.添加了 get_client 方法,对自定义参数的分解过程. #coding=utf-8 import ConfigParser import re # 对象继承自对象 ConfigParser.ConfigParser class Config( ConfigParser.ConfigParser ): ''' 提取从服务器列表数据 配置信息实例 [hosts] client = root: