javascript - 如何使用 javascript(原型(prototype))继承正确派生具有私有(private)变量的对象

标签 javascript oop inheritance prototype prototypal-inheritance

我对 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 个问题是:

  1. 我可以拥有可在派生对象中使用的私有(private)方法吗(以及 我是否应该关心它们是私有(private)的还是公开的)
  2. 我怎样才能拥有 this我想要的对象(如果可能的话,无需在派生对象中使用 function.call)
  3. 我怎样才能保留 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!'

使用 applycallbind 方法,您可以建立函数的上下文,有效地篡改 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/

相关文章:

javascript - OOP Javascript,获取类的属性而不是事件 e

ios - 多个 ViewController 继承导致 Apple Mach-O Linker Error

php - 在抽象类方法中返回抽象类的子类

java - 该对象未添加到 ArrayList 中。如何解决这个问题?

javascript - 如果是字母字符串,则将 int 解析为 0 文本

javascript - 使用 angular-ui-router 的页面标题、描述

javascript - 打破 map

javascript - GMail Contexual Gadget - 多种模式可匹配多个条件

python - 在两个 wxpython 选项卡之间共享变量

java - 线程并发——使用字符串对象的锁进行同步