我对 JavaScript 的(原型(prototype))继承很陌生,我正在尝试了解更多相关信息。 我使用一个简单的观察者模式作为示例,其中我希望从“主题”对象派生可观察对象。这就是我想做的:
function subject()
{
var callbacks = {}
this.register = function(name, callback)
{
callbacks[name] = callback;
}
this.unregister = function(name)
{
delete callbacks[name];
}
var trigger = function()
{
var a = arguments;
var t = this;
$.each(callbacks, function(name, callback)
{
callback.apply(t, a);
});
}
}
list.prototype = new subject()
function list()
{
var items = {}
this.add = function(name, item)
{
items[name] = item;
trigger('add', name);
}
this.remove = function(name)
{
delete items[name];
trigger('remove', name);
}
}
现在,当使用上面的代码时,如下所示,我遇到了第一个问题:
var l = new list()
l.register('observer1', function() { console.log(this, arguments) });
l.add('item1', 'value1'); // <-- ReferenceError: trigger is not defined, trigger('add', name);
为了继续测试,我使用 this.trigger 将触发函数设为“公开”。再次运行我的示例,我遇到了下一个问题:
var l = new list()
l.register('observer1', function() { console.log(this, arguments) });
l.add('item1', 'value1'); // <-- output: subject, ["add", "item1"]
this
对象是subject
,我希望它是 list
。我的第三个问题发生在创建另一个列表时:
var l2 = new list();
//Don;t register any observers
l2.add('item1', 'value1'); // <-- output: subject, ["add", "item1"]
callbacks
列表在 2 个列表之间共享。
我也尝试过使用 Object.create(new subject()) 进行类似的操作,但也遇到了类似的问题。
我的 3 个问题是:
- 我可以拥有可在派生对象中使用的私有(private)方法吗(以及 我是否应该关心它们是私有(private)的还是公开的)?
- 我怎样才能拥有
this
我想要的对象(如果可能的话,无需在派生对象中使用 function.call)? - 我怎样才能保留
callbacks
列表在基础对象中而不被共享?
最佳答案
一个有趣的问题。至于 #1 和 #2:假设您有一个函数 foo:
function foo() {
var _private = 'private var!';
this.access = function () {
return _private;
}
}
access
是所谓的特权方法,它是一个可以访问私有(private)变量private
的闭包。
您可以通过使用call
继承整个事物,如下所示:
function bar() {
foo.call(this);
}
var b = new bar();
console.log(b.output()); // prints 'private var!'
使用 apply
、call
和 bind
方法,您可以建立函数的上下文,有效地篡改 this
对象。 (你的第二个问题,请阅读 here )
当然,您不能在派生对象中使用完全私有(private)的方法。您需要一个访问器方法,它会破坏原始方法私有(private)的目的。话虽如此,这也是它在强类型语言中的工作方式(在 java 中,如果将一个方法标记为私有(private),甚至子类都无法访问它,它就必须受到保护)。
对于#3,我想不出如何保持回调的共享和私有(private)。 但是您可以通过简单地声明一个函数,使其成为函数的所有实例的静态属性(很像 java 等语言中的静态属性):
function foo() {
}
添加将分配给每个实例的原型(prototype)
foo.prototype.bar = // ...
和静态属性
foo.callbacks = [];
foo 的所有实例都将共享回调属性。
关于javascript - 如何使用 javascript(原型(prototype))继承正确派生具有私有(private)变量的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20467719/