如何封装对象属性以便不接管先前的对象? (原型/闭合)。

时间:2013-01-27 13:17:00

标签: javascript events closures prototype

我开始在Javascript中开始关注原型设计和闭包,但并不完全。下面这个例子,我的两个对象,第二个对象似乎丢失了范围/上下文并接管了第一个对象标识。

function broker()
{
    var _q = [];
    this.add = function(delegate) {_q[_q.length] = delegate; }
    this.broadcast = function(message)
    {
        for(qi = 0; qi < _q.length; qi++)
        {
            _q[qi](message);
        }
    }
}

function subscriber(abroker, yourname)
{
    me = this;
    this.myprop = yourname;
    this.subby = function(message){ alert(message + " " + me.myprop + me.dosomething() + secret()); };
    this.dosomething = function() {return "...abc";};
    function secret(){return "...def";}

    abroker.add(this.subby);
}

var thebroker = new broker();
var mysub = new subscriber(thebroker, 'mysub');
var myothersub = new subscriber(thebroker, 'myothersub');
thebroker.broadcast("hello from");

这个想法是有一个公共代理对象可以调用订阅者对象上的委托并执行其中的函数。但是我在代理调用的调用函数中丢失了范围。

输出: 2个警告窗口,两个输出:“myothersub”,mysub似乎失去范围?

通过在原始对象之外明确声明subby委托并引用整个对象,我已成功实现了正确的响应,例如:

而不是在订阅者对象中声明this.subby:

mysub.subby = function(message)
{
    alert(message + " " + mysub.myprop); // obv the dosomething his hidden
}

thebroker.add(mysub.subby);

如果上述任何语法错误,请原谅我直接从内存中输入。它在实践中确实有效,但失去了我习惯的封装。

如何在丢失对象的范围/上下文中使用原始技术进行封装?

1 个答案:

答案 0 :(得分:0)

简短答案:好像问题只与me构造函数中subscriber的声明有关。至少你需要在它前面放一个var,使它成为每个对象的本地/私有变量。所以var me = this;代替me = this;

说明:在JavaScript中,当您没有使用var显式声明变量时,它会使变量成为全局变量。因此,您在原始脚本中发生的事情是您创建了mysub,声明me作为this对象内mysub的全局引用。但是,只要您创建myothersub,全局me就会被覆盖到新this对象内的myothersub

因为您的subby方法创建了一个基于me的警报,所以您调用它的对象无关紧要,因为两个对象中的方法都没有使用本地或特定于对象的任何内容但仅仅引用相同的全局变量 - 最后一个要创建的对象中的this

只需编写var me = this;而不是me = this;,每次为每个创建的新对象创建一个本地版本的me,而不是覆盖的对象。

...

<强> PS。额外提示。您应该对所有变量执行此操作,以确保您拥有尽可能少的全局变量,尤其是当您不认为它们是全局变量时!因此,我会在qi构造函数中为变量broker做出相同的声明。您可以通过在循环条件内声明,例如for (var qi = 0; qi < _q.length; qi++)来完成此操作。这足以阻止qi成为全局变量。

但是,为了使代码易于阅读,最好在函数顶部声明所有变量。所以我建议简单地重写broadcast方法:

this.broadcast = function(message) {
    var qi,             // STOPS `qi` BECOMING A GLOBAL
        ql = q.length;  // SO DON'T HAVE TO CHECK LENGTH OF `q` EVERY LOOP
    for(qi = 0; qi < ql; qi += 1) {
        _q[qi](message);
    }
};

如果你之前没有遇到过他,那么道格拉斯·克罗克福德(Douglas Crockford)在关于闭包,对象创建和良好的代码编写惯例方面是一个非常好的JavaScript编写者。 this page上有很多提示,你可以很容易地找到他关于这个主题的讲座。当我开始更密切地研究JavaScript的闭包和其他方面时,这一切对我有帮助;希望它也能帮到你。