【发布时间】:2015-08-07 19:29:32
【问题描述】:
我已经被这个问题困扰了几个小时了,我似乎找不到解决方案。我有一个扩展父类的类,但我似乎无法访问在父类的构造函数中声明的变量。
我borrowed my inheritance technique。它只是使用“扩展”函数来创建子类:
//In functions.js
function extend(base, sub, methods) {
sub.prototype = Object.create(sub.prototype);
sub.prototype.constructor = sub;
sub.base = base.prototype;
for(var name in methods) { sub.prototype[name] = methods[name]; }
return sub;
}
我创建了一个名为 Stimulus 的类作为函数:
//In classes.js
function Stimulus(module_id, unit_id, attributes) {
this.attributes = attributes;
this.module_id = module_id;
this.unit_id = unit_id;
//create some other class variables based on this.attributes, this.module_id, and this.unit_id
}
Stimulus.prototype = {
_getStimulus: function() { //retrieve from database }
//other functions here
}
最后我有了子类。我用来创建它的技术也是从上面的链接中借来的:
//In classes.js
ImageStimulus = (function() {
var $this = function(module_id, unit_id, attributes) {
$this.base.constructor.call(this, module_id, unit_id, attributes);
};
extend(Stimulus, $this, {
initialize: function() {
this.fixation_cross = this.attributes['Fixation Cross'] ? this.attributes['Fixation Cross'] : false;
//do other stuff
}
//other functions here
});
return $this;
})();
这一切似乎都很简单。但是,在我的主脚本中,当我尝试运行它时,我创建了对象,然后尝试运行 initialize() 函数,一切都崩溃了:
//In main.js
var stimulus_objects = [];
for(var i = 0; i < someLimit; i++) {
//module_id is passed directly to this function
var unit_id = //some source;
var stimulus_attributes = //some source;
stimulus_objects[i] = new ImageStimulus(module_id, unit_id, stimulus_attributes);
stimulus_objects[i].initialize();
}
如果我检查控制台,我会看到上面写着
未捕获的类型错误:无法读取未定义的属性“固定交叉”
它对应于 ImageStimulus.initialize() 中我尝试调用 this.attributes['Fixation Cross'] 的行。
使Stimulus 成为ImageStimulus 的原型似乎出了点问题,因为ImageStimulus.initialize() 无法访问在Stimulus 类的构造函数中创建的this.attributes 变量。
其他人看到错误了吗?
我在 Java、C++ 甚至 PHP 方面有相当多的 OOP 编程,但这是我第一次尝试 JavaScript OOP,所以我觉得我可能犯了一些简单的错误。
编辑:以某种方式解决了问题。
所以似乎有一个相当简单的解决方案。 Stimulus 函数从未被调用过,它应该在$this.base.constructor.call() 的行上被调用。在Stimulus.prototype 对象中,我添加了constructor: Stimulus,现在Stimulus 被正确调用。我必须这样做似乎很奇怪(Stimulus() 不应该是它自己的构造函数吗?),但它有效!
Stimulus.prototype = {
constructor: Stimulus,
_getStimulus: function() {...
有谁知道为什么会发生这种情况以及为什么我的修复有效?我试图了解我做了什么。
【问题讨论】:
-
stimulus_attributes是undefined然后attributes是undefined。 -
我在
new ImageStimulus之前放了一个控制台日志,stimulus_attributes看起来与预期的完全一样。我还在输入ImageStimulus构造函数后立即记录了它,它按预期打印。但是,如果我尝试在Stimulus()函数中记录它,则不会打印任何内容;该函数甚至没有被调用。我想知道是什么原因造成的? -
如果您使用
return extend(Stimulus, $this, ...而不是return $this;会怎样? (因为extend函数返回sub。) -
错误状态,“无法读取未定义的属性'固定交叉'。”因此,您的关键字“this”的上下文抓住了错误的上下文。因此为什么“this”没有属性 fixation_cross
-
似乎有多个问题。首先,函数 Stimulus 永远不会被调用。其次,Stimulus 函数中的 this 指的是全局命名空间(窗口)。为了让“this”引用对象实例,而不是全局命名空间,必须强制执行 new。我前段时间在 Javascript 模式中读到的一种模式是将这三行包含在任何打算成为对象的函数的顶部。因此,如果它是用 new 调用的,很好,如果不是(通常)然后强制执行: if (!(this instanceof arguments.callee)) { return new arguments.callee(); }
标签: javascript class oop inheritance prototypal-inheritance