0

对于那些不熟悉的人,代理继承如下所示:

var Surrogate = function () {}

var extend = function (Base, Sub) {
  Surrogate.prototype = Base.prototype;
  Sub.prototype = new Surrogate();
  Sub.prototype.constructor = Sub;
}

var Animal = function (name) {
  this.name = name;
};

Animal.prototype.speak = function () {
  return this.getSound() + ' ' + this.name;
};

Animal.prototype.getSound = function () {
  // Abstract
};

var Cat = function (name) {
  Animal.call(this, name);
};

extend(Animal, Cat);

Cat.prototype.getSound = function () {
  return 'Meow';
};

var kitty = new Cat('Maru');
console.log(kitty.speak()); // Logs "Meow Maru"
console.log(kitty instanceof Animal); // Logs true
console.log(kitty instanceof Cat); // Logs true
console.log(kitty.constructor == Cat); // Logs true

基本上要创建一个继承自 的构造函数Animal,我们创建另一个构造函数(在本例中为),使用 的正确值Cat调用构造函数,然后使用该函数将的原型设置为没有名称属性。认为 using与except 相同是未定义的。AnimalthisextendCatAnimalextend(Animal, Cat)Cat.prototype = new Animal()Cat.prototype.name

以上工作完美,我有一个关于它的附带问题稍后。

我想把它提升到一个新的水平并隐藏Surrogate在一个闭包中,所以我改变了 and 的声明,Surrogate看起来extend像这样:

var extend = (function () {
  var Surrogate = function () {};
  return function (Base, Sub) {
    Surrogate.prototype = Base.prototype;
    Sub.prototype = new Surrogate();
    Sub.prototype.constructor = Sub;
  };
});

现在,当我运行脚本时,它在第一个日志语句中失败:

TypeError: Object [object Object] has no method 'speak'

extend.js但是,使用以下内容创建另一个文件:

var Surrogate = function () {};

module.exports = function (Base, Sub) {
  Surrogate.prototype = Base.prototype;
  Sub.prototype = new Surrogate();
  Sub.prototype.constructor = Sub;
}

extend并将主脚本中的声明更改为var extend = require('./extend');有效,并且Surrogate按预期隐藏。

对于主要问题:据我所知,node 和其他 CommonJS 系统只是将模块包装在一个闭包函数中,就像我最初尝试做的那样。为什么模块版本有效,但我的闭包版本无效?

对于上面提到的附带问题:我很惊讶Sub.prototype.constructor = Sub。我认为应该是这样,Sub.prototype.constructor = Base但这会导致最后一个日志记录语句记录false。我想我已经为自己回答了这个问题,但我认为这constructor是构造对象的属性,而不是原型。是不是反过来?

更新

我刚刚使用 AMD 使用了一个名为extend如下定义的模块进行了尝试:

define(function () {
  var Surrogate = function () {};

  return function (Base, Sub) {
    Surrogate.prototype = Base.prototype;
    Sub.prototype = new Surrogate();
    Sub.prototype.constructor = Sub;
  };
});

它工作得很好。我觉得我在这里忽略了一些非常简单的东西……为什么这在模块系统中可以正常工作,但在普通闭包中却不行?我已经在 node.js、Chrome 和 Firefox 中测试了所有版本(普通、闭包和模块)。

4

1 回答 1

1
var extend = (function () {
  var Surrogate = function () {};
  return function (Base, Sub) {
    Surrogate.prototype = Base.prototype;
    Sub.prototype = new Surrogate();
    Sub.prototype.constructor = Sub;
  };
});

应该

var extend = (function () {
  var Surrogate = function () {};
  return function (Base, Sub) {
    Surrogate.prototype = Base.prototype;
    Sub.prototype = new Surrogate();
    Sub.prototype.constructor = Sub;
  };
})();

(我只是附加()到它以执行该功能。)

或者,如果您想防止 Surrogate 损坏的可能性(某些东西可能会弄乱它的构造函数 - 让它做一些事情):

var extend = function (Base, Sub) {
    var Surrogate = function () {};
    Surrogate.prototype = Base.prototype;
    Sub.prototype = new Surrogate();
    Sub.prototype.constructor = Sub;
};
于 2012-12-30T19:11:59.417 回答