JS继承之原型继承

许多OO语言都支持两种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。如前所述,由于函数没有签名,在ECMAScript中无法实现接口继承。ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现的。

--摘自《JavaScript高级程序设计》

原型继承

原型链是实现原型继承的主要方法,基本思想就是利用原型让一个引用类型继承另一个引用类型的属性和方法。

实现原型链的基本模式:


1

2

3

4

5

6

7

8

9

10

11

12

13

function SuperType(){

 this.property=true;

}

SuperType.prototype.getSuperValue=function(){

  return this.property;

}

function SubType(){

  this.subproperty=false;

}

SubType.prototype=new SuperType();


1

SubType.prototype.getSubValue=function(){<br> return this.property;<br> }


1

var instance=new SubType();


1

instance.getSuperValue(); //true;

例子中的实例及构造函数和原型之间的关系图:

在例子代码中,定义了两个对象,subType和superType。

两个对象之间实现了继承,而这种继承方式是通过创建SuperType的实例并将该实例赋给subType.prototype实现的。实现的本质就是重写了原型对象

这样subType.prototype中就会存在一个指针指向superType的原型对象。也就是说,存在superType的实例中的属性和方法现在都存在于subType.prototype中了。这样继承了之后,又可以为subType添加新的方法和属性。

要注意,这个指针([[prototype]])默认情况下是不可以再被外部访问的,估计是会被一些内部方法使用的,例如用for...in来遍历原型链上可以被枚举的属性的时候,就需要通过这个指针找到当前对象所继承的对象。不过,Firefox、Safari和Chrome在每个对象上都支持一个属性__proto__。

原型继承需要注意的一些问题

1.别忘记默认的类型

我们知道,所有的引用类型都继承了Object,而这个继承也是通过原型链实现的。所以所有的对象都拥有Object具有的一些默认的方法。如

:hasOwnProperty()、propertyIsEnumerable()、toLocaleString()、toString()和valueOf()。

2. 确定原型和实例的关系
可以通过两种方式来确定原型和实例之间的关系。

①使用instanceof 操作符,只要用这个操作符来测试实例与原型链中出现过的构造函数,结果就会返回true。

②第二种方式是使用isPrototypeOf()方法。同样,只要是原型链中出现过的原型,都可以说是该原型链所派生的实例的原型,因此isPrototypeOf()方法也会返回true。

例子:

alert(instance instanceof Object); //true
alert(instance instanceof SuperType); //true
alert(instance instanceof SubType); //true

alert(Object.prototype.isPrototypeOf(instance)); //true
alert(SuperType.prototype.isPrototypeOf(instance)); //true
alert(SubType.prototype.isPrototypeOf(instance)); //true

③子类要在继承后定义新方法

因为,原型继承是实质上是重写原型对象。所以,如果在继承前就在子类的prototype上定义一些方法和属性。那么继承的时候,子类的这些属性和方法将会被覆盖。

如图:

④不能使用对象字面量创建原型方法

这个的原理跟第三点的实际上是一样的。当你使用对象字面量创建原型方法重写原型的时候,实质上相当于重写了原型链,所以原来的原型链就被切断了。

⑤注意父类包含引用类型的情况

如图:

这个例子中的SuperType 构造函数定义了一个colors 属性,该属性包含一个数组(引用类型值)。SuperType 的每个实例都会有各自包含自己数组的colors 属性。当SubType 通过原型链继承了SuperType 之后,SubType.prototype 就变成了SuperType 的一个实例,因此它也拥有了一个它自己的colors 属性——就跟专门创建了一个SubType.prototype.colors 属性一样。但结果是什么呢?结果是SubType 的所有实例都会共享这一个colors 属性。而我们对instance1.colors 的修改能够通过instance2.colors 反映出来。也就是说,这样的修改会影响各个实例。

原型继承的缺点(问题)

①最明显的就是上述第⑤点,有引用类型的时候,各个实例对该引用的操作会影响其他实例。

②没有办法在不影响所有对象实例的情况下,给超类型的构造函数传递参数。

有鉴于此,实践中很少会单独使用原型继承。

最近要回顾一下原生js的一些重要的基础知识点,秋招秋招。。。

转载自:http://www.cnblogs.com/LuckyWinty/

时间: 2024-10-04 23:37:32

JS继承之原型继承的相关文章

node.js javascript理解原型继承

util.inherits util.inherits(constructor, superConstructor)是一个实现对象间原型继承的函数. JavaScript 的面向对象特性是基于原型的,与常见的基于类的不同.JavaScript 没有提供对象继承的语言级别特性,而是通过原型复制来实现的 var util = require('util'); function Base() { this.name = 'base'; this.base = 1991; this.sayHello =

JS中“类”继承和原型继承

类继承: 先用函数构造器创建了一个“类”Student,然后在Student原型上定义了一个方法sayHello,然后创建了一个"类“PrimaryStudent,用apply()初始化PrimaryStudent. 然后让PrimaryStudent的原型等于Student创建的对象,并把PrimaryStudent原型上的构造器指向当前”类“,即PrimaryStudent,注意红色加粗部分. 1 function Student(name){ 2 this.name = name; 3 }

javascript继承,原型继承,借用构造函数继承,混合继承

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getS

关于js的对象原型继承

javascript中,对象的继承是通过原型去继承. 可以这样理解:js中的对象,包含的除了属性和方法,还有一个最基本的原型__proto__对象.这个原型__proto__指向谁,这个对象就继承谁.这是最容易理解对象原型继承的一种方式. 如下面的代码: var student={ name:'zhangsan', age:21, run:function(){ return this.name+' is running!'; } }; var xiaoming={ name:'xiaoming

js方法和原型继承(一)

在js语言规范中并不存在方法这一概念,方便起见,将作为对象属性的函数成为方法this引用的规则a.在最外层代码中,this引用的是全局对象b.在函数内,this引用根据函数调用方式不同而不同函数内部的this引用 见下表 函数的调用方式 this引用的引用对象 构造函数调用 所生成的对象 方法调用 接收方对象 apply或call调用 由apply或call的参数指定的对象 其它方式调用 全局对象 接收方对象是这样一种对象通过点运算符或者中括号运算符调用对象方法时,在运算符左侧所指定的对象下面是

JS面向对象组件 -- 继承的其他方式(类式继承、原型继承)

继承的其他形式: •类式继承:利用构造函数(类)继承的方式 •原型继承:借助原型来实现对象继承对象 类 : JS是没有类的概念的 , 把JS中的构造函数看做的类 要做属性和方法继承的时候,要分开继承. function Aaa(){ //父类 this.name = "小明"; } Aaa.prototype.showName = function(){ alert( this.name ); }; function Bbb(){ //子类 } Bbb.prototype = new

JS中的原型继承机制

转载 http://blog.csdn.net/niuyongjie/article/details/4810835 在学习JS的面向对象过程中,一直对constructor与prototype感到很迷惑,看了一些博客与书籍,觉得自己弄明白了,现在记录如下: 我们都知道,在JS中有一个function的东西.一般人们叫它函数.比如下面的代码 js代码: [javascript] view plaincopy function Person(name) { alert(name); } Perso

JS中的原型继承和多重继承

概念:1原型继承是创建新类型对象----子类型,子类型基于父类型,子类型拥有父类型所有的属性和方法(从父类型继承得到),然后修改其中的部分内容或者添加新的内容.继承最好在子类型模型可以被视为父类型对象的时候使用.   2从多个父类型中派生出一个对象类型称为多重继承. 原型继承: 使用new关键字和构造函数的prototype属性都是定义类型的特定方式,这些是我们到目前为止一直使用的,对于简单的对象,这种方式还是很好的,但是当程序过度使用继承时,这种创建对象的方法很快就显得笨拙了.所以增加一些函数

js组合继承(原型继承+借用构造函数继承)

组合继承就是将原型链和构造函数结合起来发挥二者优势的一种模式.继承:是类型与类型之间的继承继承目的:把子类型相同成员提取到父类型,实现代码重用 大体思路是:使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承,很好地解决了原型链继承的缺点,是较为常用的一种继承方式.//一:借用构造函数(借用父类型extend) 缺点:无法继承父类型的方法//父类型 function Person(name,age,sex){ this.anme=name;this.age=age;th