0

In another SO question about whether to call a super-constructor or use the prototype chain the answer provided by one of the users seemed sensible but didn't work for me when I implemented it on my solution which has multiple layers of inheritance.

Here's the answer I'm referring to: https://stackoverflow.com/a/4389429/392591

So I've created a jsFiddle using this custom extend method to illustrate the problem: https://jsfiddle.net/68q7yghv/
I've added the jsFiddle code at the bottom.

In my test I've created a 4 tier class inheritance structure from baseClass through to subSubSubClass each of which (except the baseClass) use the 'extend' method to inherit from the previous sub-class. When you hit the test button I'm printing out class.baseClassMethod to see if it finds it, but it only finds it for the base class.

You should see the following results: function () { this.output += "baseClassMethod"; }
undefined
undefined
undefined

Is it possible that the cause is that the call to the super constructor is messing with the 'this' context?

function extend(baseClass, subClass) {
  var originalPrototype = subClass.prototype;
  subClass.prototype = Object.create(baseClass.prototype);
  for (var key in originalPrototype) {
    subClass.prototype[key] = originalPrototype[key];
  }
  subClass.prototype.constructor = subClass;
  Object.defineProperty(subClass.prototype, 'constructor', {
    enumerable: false,
    value: subClass
  });
};

var baseClass = function() {
  this.output = "Base: ";
  this.toggleWizardHandlers = [];
  this.baseClassMethod = function() {
    this.output += "baseClassMethod";
  };
};

baseClass.prototype.on = function(eventName, handler) {
  switch (eventName.toLowerCase()) {
    case "togglewizards":
      return this.toggleWizardHandlers.push(handler);
      break;
  }
};

baseClass.prototype.toggleWizards = function(newWizard, newStepIndex) {
  var handler, i, len, ref;
  ref = this.toggleWizardHandlers;
  for (var i = 0; i < ref.length; i++) {
    handler = ref[i];
    setTimeout(handler, 0, newWizard, newStepIndex);
  }
};

var subClass = function() {
  baseClass(this);
};
extend(baseClass, subClass);

var subSubClass = function() {
  subClass(this);
};
extend(subClass, subSubClass);

var subSubSubClass = function() {
  subSubClass(this);
};
extend(subSubClass, subSubSubClass);

var manager = function(settings) {

  this.log = function(message) {
    $("#log").html($("#log").html() + "<br />" + message);
  };
  this.clearLog = function() {
    $("#log").html("");
  };

  this.testBaseClass = new baseClass();
  this.testSubClass = new subClass();
  this.testSubSubClass = new subSubClass();
  this.testSubSubSubClass = new subSubSubClass();

  //test.on("toggleWizards", function(param) {    that.log(param);  });
};

$(function() {
  var manage = new manager("");

  $("#btn").click(function() {
    manage.log("start test");
    manage.clearLog();

    try {
      manage.log(manage.testBaseClass.baseClassMethod);
    } catch (e) {
      manage.log(e);
    }

    try {
      manage.log(manage.testSubClass.baseClassMethod);
    } catch (e) {
      manage.log(e);
    }

    try {
      manage.log(manage.testSubSubClass.baseClassMethod);
    } catch (e) {
      manage.log(e);
    }

    try {
      manage.log(manage.testSubSubSubClass.baseClassMethod);
    } catch (e) {
      manage.log(e);
    }
  });

});
4

2 回答 2

2

您的原型继承工作正常,您可以尝试访问on或访问toggleWizards所有实例。

但是,您在构造函数中的超级调用缺少关键部分:.call. 没有它,您将传递this第一个参数,而不是作为this参数。如果没有这个,您的基类将无法初始化子类实例上的任何属性:

function subClass() {
    baseClass.call(this);
//            ^^^^
}
于 2016-02-29T09:52:50.000 回答
1

当你调用超级构造函数时,你需要使用apply,而不是把它作为一个简单的函数来调用。

var subClass = function() {
    baseClass.apply(this);
};

否则,您的子类新this对象将作为第一个参数传递给超级构造函数,this并将引用全局对象(或在严格模式下为 null)。

一件小事,大写构造函数很常见,因此很明显它们应该被调用new而不是作为常规函数。

于 2016-02-29T09:48:41.220 回答