这是我的超类:
function Element() {
var name;
this.setName(n) = func()...{};
this.getName() = func()..{return name};
}
我的另一个孩子班:
Select = null;
...
Select =
function (n) {
if (typeof n !== "undefined")
this.setName(n);
...
}
Select.prototype = new Element();
Select.prototype.constructor = Select;
那么,我在谈论什么样的“怪异时刻”?这是:
var e1 = new Select("element1");
e1.getName(); // return "element1"
var e2 = new Select(); // WITHOUT NAME
e2.getName(); // return "element1"!!! should be ""!
这是一个相当可预测的行为,但如何解决这个问题呢?
当然,我可以在this.clear()
中创建类似Element
的内容,它会清除属性并将此方法放在Select
函数中,但也许有一个合适的解决方案?
答案 0 :(得分:3)
您应该将此行Element.call(this, n)
添加到Select
。这很难解释,我觉得脾气暴躁,因为我不喜欢javascript中的假私有属性,但是,我必须提供一些细节,以便你了解你目前在做什么,否则我将无法到达睡眠。
因此,new Element()
创建一个新的上下文,name
可以在不打扰任何人的情况下生活。此外,还创建了两个名为setName
和getName
的新函数,并绑定到prototype
的{{1}}对象。
从现在开始,如果您创建Select
的新实例,则可以调用这些函数,因为它们在实例的原型中可用。这实际上发生在Select
。实际上,new Select("element1")
已定义,因此n
从setName
调用,它引用实例。
但最重要的是,将this
设置为setName
时调用n
也会将"element1"
设置为name
。然后,如果您创建了"element1"
的第二个实例,但未定义Select
,则不会调用n
,因此,setName
仍设置为name
,对于两个实例。
为什么为两个实例?因为两个实例共享相同的"element1"
方法,绑定到原型的方法,并且此方法引用唯一的setName
变量 - 请记住name
仅被调用一次。
最后,为什么新行Element
会阻止Element.call(this, n)
被分享?因为每次调用name
都会创建一个新的上下文,也就是说,新的Element
,新的name
和新的setName
,并将这两种方法绑定到新创建的实例。
嗯,希望这是你的早晨,如果你因我的错而陷入睡眠障碍,我会很抱歉......
正如Bergi和HMR所提到的,这种创建原型的方式 - getName
- 已经过时了,会让你陷入死胡同。请记住,原型是用于创建实例的模板。知道这一点并考虑你的代码,我们至少可以做两个观察:
Child.prototype = new Parent
内的内容 - 被不必要地执行,因为目前的目标是设置将在其上创建实例的模板。Element
中需要name
,否则您的程序会崩溃。你会给原型什么名字?这个问题显然没用,因为你不想给模板命名。要绕过这些问题,您需要一个中间人,如下面的代码所示(从Bergi共享的link复制)。如您所见,原型的创建被委托给一个空的“虚拟”构造函数。这样做可以解决上面提出的两个问题。
new Element(name)
或者,您可以使用内置的function Dummy () {}
Dummy.prototype = Element.prototype;
Select.prototype = new Dummy();
Select.prototype.constructor = Select;
:
Object.create()
进一步阅读:
答案 1 :(得分:2)
您应该使用Element
的原型,以便不在实例之间共享变量:
function Element() {}
Element.prototype.setName = function(n) { this.name = n; };
Element.prototype.getName = function() { return this.name; };
在这种情况下,e2.getName()
将返回undefined
。