2013-03-21 57 views
0

我正在寻找简化Javascript中的继承。从我目前为止收集到的好办法,实现“继承”,“阶级”之间如下:我可以在Javascript中编写“扩展”继承函数吗?

function ParentClass() { 
    //Parent Constructor 
} 

ChildClass.prototype = new ParentClass(); //Step 1: Use parent as prototype 
ChildClass.prototype.constructor = ChildClass; //Step 2: Designate appropriate constructor 
function ChildClass() { 
    ParentClass.call(this, arguments); //Step 3: Call the parent's constructor from the child's 

    //Child Constructor 
} 

我喜欢的过程分为三“步”正如我上面标记(第1步,2和3)。我想所有这三个步骤放进一个功能(从Java背景的,我已经标记为“扩展”),我可以从函数构造对象调用,就像这样:

function ParentClass() { 
    //Parent Constructor 
} 

ChildClass.extend(ParentClass); //Execute steps 1, 2 and 3 all in this function 
function ChildClass() { 
    //Child Constructor 
} 

这是我到目前为止:

Function.prototype.extend = function (parent) { 
    var oldConstructor = this.prototype.constructor; 
    this.prototype = new parent(); //Step 1 
    this.prototype.constructor = function (arguments) { //Step 2 
     parent.apply(this, arguments); //Step 3 
     oldConstructor(arguments); 
    }; 
} 

扩展功能的步骤1和2在此上下文中工作正常,但步骤3给我的问题。我试图做的是用一个新的函数替换Child的构造函数,该函数调用父构造函数,然后调用Child的构造函数。但是,当我运行这个父构造函数没有被调用。我一直无法确定问题(我是否正确使用“this”关键字?);也许我正在接近这个错误的方式。有可能做出这样的功能,对吧?我怎样才能使工作“扩展”功能?

UPDATE:

真正的问题似乎在于我使用了“这个”关键字。这里是我现在看的代码:

function ParentClass(x) { 
    this.value = x; 
} 

function ChildClass() { 
} 
ChildClass.extend(ParentClass); 


function testtest() { 
    var a = new ParentClass("hello world"); //Alerts "hello world" 
    alert(a.value); 
    var b = new ChildClass("hello world"); //Alerts "undefined" 
    alert(b.value); 
} 

为什么第一次警报工作,第二次警报不工作?我认为“this”是指函数正在运行的上下文,在这两种情况下都是调用构造函数(a或b)的对象。

+0

我只是想你的扩展功能,并在父类的构造被称为。你能举一个例子,说明它不适合你吗? – user18477575 2013-03-21 20:03:59

+0

这个问题似乎与“this”关键字一样。属性在我的父构造函数(this.x = y)中设置,但这些属性不适用于Child对象实例。所有函数都被调用,但属性没有按照我的预期设置。 – Noah 2013-03-23 22:11:06

回答

2

如果你真的想这样做,也许你应该只使用Coffeescript。或者至少从中得到一些想法。

它在Javascript的基础上透明地提供了support for classes and inheritance,并且使用了与您在此处使用的几乎相同的想法。

如果这是一项学术活动,尽一切可能进行(并了解Coffeescript如何为创意提供帮助)。但除此之外,没有必要重新发明轮子。

对于直接比较,以下内容粘贴到http://js2coffee.org/

class Shape 
    area: -> undefined 
    name: -> "Shape" 

class Rectangle extends Shape 
    constructor: (w, h) -> 
    @w = w 
    @h = h 

    area: -> 
    @w * @h 

    name: -> "Rectangle" + super 

一个Rectangle的name()现在将返回RectangleShape。这个名字很愚蠢,但让你了解super的工作原理。

它看起来像什么在JS(注意在__extends功能全部管道):

var Rectangle, Shape, 
    __hasProp = {}.hasOwnProperty, 
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; 

Shape = (function() { 

    function Shape() {} 

    Shape.prototype.area = function() { 
    return void 0; 
    }; 

    Shape.prototype.name = function() { 
    return "Shape"; 
    }; 

    return Shape; 

})(); 

Rectangle = (function(_super) { 

    __extends(Rectangle, _super); 

    function Rectangle(w, h) { 
    this.w = w; 
    this.h = h; 
    } 

    Rectangle.prototype.area = function() { 
    return this.w * this.h; 
    }; 

    Rectangle.prototype.name = function() { 
    return "Rectangle" + Rectangle.__super__.name.apply(this, arguments); 
    }; 

    return Rectangle; 

})(Shape); 
+0

__extends函数似乎或多或少是我试图完成的;有一点适应性,我可以像使用我自己的extend()函数一样使用它。谢谢! – Noah 2013-03-25 05:59:27

1

注意到,在你的第二块中的代码不执行相同的顺序步骤。在调用extend之后声明函数时,它会覆盖由extend函数创建的构造函数。首先尝试宣告你的子类,然后扩展它:

这个工作对我来说:

function Parent() { 
    console.log("Parent Constructor"); 
} 

function Child() { 
    console.log("Child Constructor"); 
} 

Child.extend(Parent); 

new Child() 

输出:

Parent Constructor 
Child Constructor 
+0

无论“extend()”和函数声明的顺序如何,实际上都会调用这两个构造函数。不过谢谢你的帮忙。我错误地写了我的问题,现在我已经更新了它。 – Noah 2013-03-23 22:20:35

相关问题