简体   繁体   English

我可以用Javascript编写“扩展”继承函数吗?

[英]Can I Write an “Extend” Inheritance Function in Javascript?

I'm looking to simplify inheritance in Javascript a bit. 我希望稍微简化Javascript的继承。 From what I've gathered so far, a good way to achieve "inheritance" between "classes" is as follows: 根据到目前为止的经验,实现“类”之间的“继承”的一种好方法如下:

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
}

I like to divide the process into three "steps" as I labeled above (Step 1, 2 and 3). 我喜欢将过程分为上面所述的三个“步骤”(步骤1、2和3)。 I would like to put all three of these steps into one function (coming from a Java background, I've labeled it "extend") that I can call from the function constructor object, like so: 我想将所有这三个步骤放到一个可以从函数构造函数对象调用的函数中(从Java背景开始,我将其标记为“ extend”):

function ParentClass() {
    //Parent Constructor
}

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

This is what I have so far: 这是我到目前为止的内容:

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);
    };
}

Steps 1 and 2 of the extend function work fine in this context, but Step 3 is giving me issues. 在这种情况下,扩展功能的步骤1和2可以正常工作,但是步骤3给了我一些问题。 What I am attempting to do is replace the Child's constructor function with a new function that calls the parent Constructor, and then the Child's constructor. 我试图做的是用一个新的函数替换Child的构造函数,该函数先调用父构造函数,然后再调用Child的构造函数。 However when I run this the parent constructor is not being called. 但是,当我运行此父构造函数没有被调用。 I haven't been able to nail down the problem (am I using the "this" keyword correctly?); 我无法确定问题所在(我是否正确使用了“ this”关键字?); perhaps I am approaching this the wrong way. 也许我正以错误的方式来对待。 It is possible to make a function that does this, right? 可以创建一个执行此功能的功能,对吗? How can I make a working "extend" function? 如何使工作的“扩展”功能?

UPDATE: 更新:

The real problems seems to lie with my use of the "this" keyword. 真正的问题似乎在于我对“ this”关键字的使用。 Here is the code I am looking at now: 这是我现在正在查看的代码:

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);
}

Why does the first alert work and second does not? 为什么第一个警报有效而第二个警报无效? I thought that "this" refers to the context in which a function is running, which in both cases would be the object calling the constructor (a or b). 我认为“ this”是指函数在其中运行的上下文,在两种情况下,这都是调用构造函数(a或b)的对象。

If you really want to do this, perhaps you should just use Coffeescript . 如果您真的想这样做,也许应该只使用Coffeescript Or at least get some ideas from it. 或者至少从中得到一些想法。

It provides support for classes and inheritance transparently on top of Javascript, and does it using pretty much the same ideas you are using here. 它在Javascript的基础上透明地提供了对类和继承的支持 ,并且使用与您在此处使用的几乎相同的思想来做到这一点。

If this is an academic exercise, by all means go ahead (and check out how Coffeescript does it for ideas). 如果这是一项学术活动,则一定要继续(并查看Coffeescript如何做到这一点)。 But otherwise, there's no need to reinvent the wheel. 但是,否则,无需重新发明轮子。

For a direct comparison, paste the following into http://js2coffee.org/ 为了进行直接比较,请将以下内容粘贴到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

A Rectangle's name() would now return RectangleShape . 一个Rectangle的name()现在将返回RectangleShape The name thing is silly, but gets you an idea of how super works. 这个名字很愚蠢,但是却让您了解了super工作原理。

What it looks like in JS (note all the plumbing in the __extends function): 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);

Noticed that the code in your 2nd block does not execute the steps in the same order. 注意,您的第二个块中的代码不会以相同的顺序执行步骤。 When you declare the function after calling extend, it overrides the constructor that is created by the extend function. 在调用extend之后声明函数时,它会覆盖由extend函数创建的构造函数。 Try declaring your child class first, and then extending it: 尝试先声明您的子类,然后扩展它:

This works for me: 这对我有用:

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

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

Child.extend(Parent);

new Child()

Outputs: 输出:

Parent Constructor
Child Constructor

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM