javascript 对象继承支不支持继承

JavaScript中的继承五种方式_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
JavaScript中的继承五种方式
上传于||暂无简介
阅读已结束,如果下载本文需要使用1下载券
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩2页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢Javascript:继续实现继承,支持:this.callParent(arguments)
在中,我简单的介绍了如何实现单继承。只是在子类中调用父类方法的方式让人感觉不是很爽:
1 var Animal = function () {
Animal.super().constructor.apply(this, arguments);
今天这篇文章的目的就是简化这种调用方式,期望的调用方式如下:
1 var Animal = function () {
this.callParent(arguments);
如何实现callParent呢?&
只要做到如下几点,实现callParent就不是问题了,要求如下:
callParent必须知道哪个方法调用的它。
callParent必须知道调用它的那个方法的名字。
callParent必须知道调用它的那个方法的拥有者(prototype)。
callParent必须知道调用它的那个方法的拥有者的父类。
思路有了,实现就不是问题了
因为默认情况Javascript只支持1,而2、3和4都要在框架层面做出约束,框架要做的就是:一、为类型和方法增加相应的元数据;二、类型的方法定义必须使用Class.defineMethod方法进行定义。
在中,我简单的介绍了如何实现单继承。只是在子类中调用父类方法的方式让人感觉不是很爽:
1 var Animal = function () {
Animal.super().constructor.apply(this, arguments);
今天这篇文章的目的就是简化这种调用方式,期望的调用方式如下:
1 var Animal = function () {
this.callParent(arguments);
如何实现callParent呢?&
只要做到如下几点,实现callParent就不是问题了,要求如下:
callParent必须知道哪个方法调用的它。
callParent必须知道调用它的那个方法的名字。
callParent必须知道调用它的那个方法的拥有者(prototype)。
callParent必须知道调用它的那个方法的拥有者的父类。
思路有了,实现就不是问题了
因为默认情况Javascript只支持1,而2、3和4都要在框架层面做出约束,框架要做的就是:一、为类型和方法增加相应的元数据;二、类型的方法定义必须使用Class.defineMethod方法进行定义。
1 Function.prototype.defineMethod = function (methodName, methodBody) {
this.prototype[methodName] = methodB
3&& methodBody.$name = methodN
this.$owner = this;
7 Function.prototype.extend = function (baseType) {
var tempType = function () { };
tempType.prototype = baseType.
this.prototype = new tempType();
this.prototype.constructor = this;
this.prototype.callParent = function () {
var method = arguments.callee.
return method.$owner.$baseType.prototype[method.$name].apply(this, arguments);
this.$baseType = baseT
this.defineMethod('constructor', this.prototype.constructor);
this.super = function () {
return baseType.
var Base = function (name) {
console.log('Base');
this.name =
var Animal = function () {
this.callParent(arguments);
console.log('Animal');
Animal.extend(Base);
var Dog = function () {
this.callParent(arguments);
console.log('Dog');
Dog.extend(Animal);
var dog = new Dog('懒狗');
------------------------------------
整个实现有点借鉴ExtJS,当然ExtJS实现的就更完美了。我也有想法,希望把ExtJS的核心移植到NodeJS中。
框架地址:
博客地址:
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。javascript中的面向对象编程与继承机制
简单总结,不确保所总结的是对的,仅作为梳理思路之用。
===================我是js的分割线=======================================================
面向对象编程首先要创建对象,由于javascript的松散的数据特点,因此其创建对象的方式有以下几种:
1.创建Object实例,然后再给它添加属性与方法。
var person = new Object();
person.age = 15;
person.tellAge = function() {
& alert(this.age);
这种方法不好之处在于,每创建一个对象的实例,都要重复写一遍上面的代码,会带来大量的代码的重复。
2.工厂模式。
用createXXX来包装第一种方法。
function createPerson(age) {
& var o = new Object();
& o.tellAge = function() {
alert(this.age);
var zhangsan = createPerson(15);
var lisi = createPerson(34);
这种方法比第一种方法的代码冗余要少,但是会在每一个实例中都保存一份对象的方法变量的副本,尽管这些方法变量是一模一样的。另外,工厂模式没有解决对象的识别问题,即,在使用instanceof
操作符的时候,只会对Object返回true。
3.构造函数模式。
function Person(age) {
& this.age =
& this.tellAge = function() {
alert(this.age);
var zhangsan = new Person(15);
var lisi = new Person(34);
这样产生的对象的实例,都有一个contructor属性,指向其构造函数(这里是Person),也解决了对象识别的问题(即,在这里,zhangsan
和lisi 对于instanceof操作符,对于Person 和
Object都返回true)。但是,仍然有和第二种构造对象的方法一样的代码冗余问题。
4.原型模式。
js中创建的每一个函数/对象都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象所包含的就是那些特定类型的对象的实例所共享的那些属性。从这个意义上讲,prototype属性与c++中的static属性很相似。所以,不必在构造函数中添加通用的属性,而应该把它们都放到prototype(原型)属性中去。prototype属性中也自动添加了一个contructor属性,指向其所包含的函数。
如果使用某个函数作为构造函数创建了一个实例,则该实例中存在着一个__proto__的属性,指向了其构造函数的prototype对象。当访问该实例的某一个属性时,首先会在该实例本身中查找,然后再在__proto__中查找。使用hasOwnProperty()方法可以检测一个属性是存在于实例中,还是prototype对象中。
function Person() {}
Person.prototype.age = 15;
Person.prototype.tellAge = function() {
& alert(this.age);
var zhangsan = new Person();
var lisi = new Person();
lisi.age = 34;
这里,修改lisi.age是修改了lisi这个实例中的age属性,并没有修改lisi的__proto__中的age属性,而由于js对于属性的查找顺序,看起来就好像是修改了lisi的age一样。可以使用delete操作符来删除实例中的属性从而暴露出原型中的属性。
另外,为了美观,可以采用字面量来写prototype,但这相当于重写了构造函数的prototype属性,因此其contructor将不再指向原构造函数,而是Object的构造函数,也可以手动重写contructor;
function Person() {}
Person.prototype = {
& constructor: Person,
& age: 15,
& tellAge: function() {
alert(this.age);
person zhangsan = new Person();
person lisi = new Person();
千万不要在实例化对象后再以字面量的方式修改构造函数的prototype属性,因为这样会导致实例中的__proto__指针指向的和构造函数中prototype属性指向的不是一个对象!
原型模式一个比较突出的问题是:所有属性都是共享的,实例除了用实例属性隐藏原型属性外,没有自己独特的属性。这种情况在属性值是一个类型引用值时显得比较明显。因此,可以考虑构造函数与原型函数组合的方法来实现对象构造。
5.组合模式
function Person(age) {
& this.age =
Person.prototype = {
& constructor: Person,
& tellAge: function() {
alert(this.age);
这种模式几乎是创建对象的一种默认模式。
另外,还有动态原型模式(推荐),寄生构造函数模式(不推荐),稳妥构造函数模式(条件推荐)等构造对象的方法。参阅《javascript高级程序设计(第2版)》
================================我是js的分割线===================================================
下面说说继承。
javascript支持实现继承,不支持接口继承。继承主要是通过原型链来实现的。
在js中,每一个构造函数(其实函数均可)都有一个prototype对象,每一个对象的实例都有一个__proto__指针指向其构造函数的prototype对象。如果,我们让一个构造函数(SubClass)的prototype对象等于另一个构造函数(SuperClass)的实例,那么SubClass的实例(instance)就将存在一个instance.__proto__.__proto__的属性,如果这个过程一直迭代下去,就构成了一个原型链,根据前面说过的js中属性的搜索机制,就据此实现了继承。
注意:给子类的原型添加方法或者修改原型方法一定要在将子类的原型替换成父类实例之后进行,否则由于在构造函数中所保存的原型是一个指针的缘故,会导致修改无效。
原型链存在两个问题:第一,由于原型链是通过将子类的原型赋值为父类的实例来继承的,那么父类的成员变量(即构造函数中定义的,不用于共享的变量)将成为子类原型的变量,也就是变成了共享的变量,这显然不是我们想要的;第二,无法在替换子类原型时为父类的构造函数传递参数。
因此有了以下几种比较复杂的继承模式:
1.借用构造函数。
借用构造函数的思想是在子类的构造函数中调用父类的构造函数,如下代码所示:
function SuperClass(name) {
&&& this.name =
function SubClass(name) {
SuperClass.call(this, name);
var zhangsan = SubClass("zhangsan");
这种继承方式的问题是:第一,只能通过构造函数来构造对象(无论是子类还是父类),无法通过prototype实现方法属性的代码复用;第二,在父类原型中定义的方法,在子类中是不可见的;第三,在子类中调用父类构造函数,传递参数时,其实只是在子类的实例中添加了一个和父类同名的属性,并没有改写父类的属性的值。
鉴于此,这种模式很少单独使用。
2.组合继承。
其核心思想是通过原型链实现对方法属性等需要共享的属性的继承,而通过借用构造函数实现对非共享属性的继承。
function SuperClass(name, age) {
& this.name =
& this.age =
SuperClass.prototype.tellAge = function() {
& alert(this.age);
function SubClass(name, age, sex) {
& SuperClass.call(this, name, age);//第二次调用
& this.sex =
SubClass.prototype = new SuperClass();//第一次调用
SubClass.prototype.tellSex() {
& alert(this.sex);
var instance = new SubClass("zhangsan", 25, "male");
这种继承方式,既实现了方法属性的代码复用,又保留了非共享的成员属性。但是,其中也有问题。在构造SubClass的实例的过程中,对父类SuperClass的构造函数调用了两次。在替换子类原型的第一次调用中,子类原型中存在了name和age两个变量(值都是undefined),而在子类构造函数中的那次调用中,为子类的实例添加了name和age两个变量,覆盖掉了原型中的两个变量。因此,这样是存在资源浪费的。之后会通过另一种继承模式解决这一问题。
3.原型式继承
以一个对象的实例为基础,将其复制给另一个对象的__proto__属性,实现某种意义上的继承。
function object(o) {
& function F() {};
& F.prototype =
& return new F();
person = {
& name: "zhangsan",
var child = object(person);
child.name = "Greg";
child.sex = "female";
这种继承相当于是对于基础对象的一次浅复制,可以使新对象与基础对象保持相似。当然,这种继承中,基础对象的所有属性都是共享的。
4.寄生式继承
function createAnother(original) {
& var clone = object(original);
& clone.sayHi = function() {
alert("Hi");
person = {
& name: "Greg",
& age: "16"
var zhangsan = createAnother(person);
zhangsan.sayHi();
5.寄生组合式继承
寄生组合式继承主要是为了解决3中组合是继承的冗余问题的。
前述组合式继承产生冗余的原因是,我们在替换子类的原型时,调用了父类的构造函数,从而带来了父类的非共享属性。而这是不必要的,我们其实只需要将父类的原型的一份副本赋给子类的原型即可,也就是,我们只需要子类的原型和父类的原型相似即可,这就用到了我们前面提到的寄生式/原型式继承。
function inheritPrototype(subClass, superClass) {
& var prototype =
object(superClass.prototype);
& prototype.constructor = subC
& subClass.prototype =
function SuperClass(name, age) {
& this.name =
& this.age =
SuperClass.prototype.tellAge = function() {
& alert(this.age);
function SubClass(name, age, sex) {
& SuperType.call(this, name, age);
& this.sex =
inheritPrototype(SubClass, SuperClass);
SubClass.prototype.sayHi = function() {
& alert("Hi");
很多流行的javascript库中的extend函数就是采用的这种继承方式。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。如何理解关于JavaScript语言精粹----继承这章中的一个说法?
在继承这章第50页中有一句话&br&“我们现在有了行为像类的构造器函数,但仔细看&b&他们&/b&,你会惊讶的发现,没有私有环境,所有属性都是公开的,并且&b&无法访问 super(父类)的方法&/b&。”&br&我有几个问题&br&1.这里不知道是不是翻译的问题,读起来“&b&他们&/b&”像是指的构造函数,但是我看了好几遍感觉说的应该是构造函数构造出的实例吧。&br&2.所有属性是公开的我能理解,但是&b&无法访问父类的方法&/b&是什么意思,用这种方法构造出的实例明明是能继承到父类的方法的啊。联系作者在函数化构建对象的最后的一个例子(就是myCoolCat那个)我只能理解成是当子类的方法名与父类的方法名相同时,我们就无法再调用父类的这个方法。比如下面这段&br&&div class=&highlight&&&pre&&code class=&language-text&&
function Person(name) {
this.name =
Person.prototype.getName = function () {
console.log(this.name + '我是父类的');
function Student(name) {
this.name =
Student.prototype = new Person();
Student.prototype.getName = function () {
console.log(this.name);
var s = new Student('lyc');
s.getName();
&/code&&/pre&&/div&但是就算方法名相同,也依然可以获取父类的getName方法啊,比如下面这段&br&&div class=&highlight&&&pre&&code class=&language-text&&
function Person(name) {
this.name =
Person.prototype.getName = function () {
console.log(this.name + '我是父类的');
function Student(name) {
this.name =
Student.prototype = new Person();
//获取父类的getName
Student.prototype.get_Name = Student.prototype.__proto__.getN
Student.prototype.getName = function () {
console.log(this.name);
var s = new Student('lyc');
s.getName();
s.get_Name();
&/code&&/pre&&/div&&br&&br&所以这里是我在哪一出理解有偏差吗?
在继承这章第50页中有一句话“我们现在有了行为像类的构造器函数,但仔细看他们,你会惊讶的发现,没有私有环境,所有属性都是公开的,并且无法访问 super(父类)的方法。”我有几个问题1.这里不知道是不是翻译的问题,读起来“他们”像是指的构造函数,但是我看了好几遍感觉说的应该是构造函数构造出的实例吧。2.所有属性是公开的我能理解,但是无法访问父类的方法是什么意思,用这种方法构造出的实例明明是能继承到父类的方法的啊。联系作者在函数化构建对象的最后的一个例子(就是myCoolCat那个)我只能理解成是当子类的方法名与父类的方法名相同时,我们就无法再调用父类的这个方法。比如下面这段
function Person(name) {
this.name =
Person.prototype.getName = function () {
console.log(this.name + '我是父类的');
function Student(name) {
this.name =
Student.prototype = new Person();
Student.prototype.getName = function () {
console.log(this.name);
var s = new Student('lyc');
s.getName();
那要是生的都是女儿,又嫁到别的村庄养老就指着你的70元一个月的养老金女婿继承不了老人的房产,能给你养老你明说要我到了干不动活就上吊死了给你省下那70元就行了
已有帐号?
无法登录?
社交帐号登录

我要回帖

更多关于 javascript 多继承 的文章

 

随机推荐