1

我开始关注 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);

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

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

4

1 回答 1

0

简短的回答:看起来问题只是与您mesubscriber构造函数中的声明有关。至少您需要var在它前面放置一个以使其成为每个对象的本地/私有变量。所以var me = this;代替me = this;.

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

因为您的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 编写者,涉及到闭包、对象创建和良好的代码编写约定。此页面上有很多提示,您可以很容易地找到他就该主题进行演讲的视频。当我开始更仔细地研究闭包和 JavaScript 的其他方面时,所有这些都对我很有帮助。希望它也能帮助你。

于 2013-01-27T14:24:21.703 回答