防止函数在外部作用域中查找变量

3

我希望这样做是因为我的项目通常使用像下面这样的快捷变量:

(function() {
    var world = new World(),
        Event = world.Event,
        Guide = world.Guide;

    Event.add('updateUI', function() {
        // 1st: Correct, the value of 'this' refers to a world
        this.Guide.show('UI updated');
        // 2nd: Ok because 'world' was defined in outer scope
        world.Guide.show('UI updated');
        // 3rd: Ok because 'Guide' was defined in outer scope
        Guide.show('UI updated');
    });
})();

如果我将 Event.add('updateUI', function() { ... }); 移动到其他文件中,只有第一条语句 (this.Guide.show) 能够正常工作。如何防止该函数使用外部范围的 worldGuide 变量,使得第二和第三条语句从一开始就会抛出错误。 use strict 很接近这个要求,但它仅仅防止你获取全局对象。
更新以使此问题更清晰:主要问题是:是否有任何方法可以防止函数查找外部范围的变量?如果没有,请解释原因,因为我认为这是一个合理的需求。

5
你所建议的做法行不通,编程语言本质上只能按照它们设计的方式工作。将函数内的代码移入另一个文件中会导致代码从当前函数中脱离,进入到一个新的上下文中。你应该描述一下你想要实现的目标,因为这个问题本身并不太合理。 - Pointy
1
这被称为闭包。它是Javascript最有用的功能之一;你无法禁用它。 - SLaks
我本来想写你想要违背语言规则,这样做不是一个好主意,但@Pointy表达得更好 :D - Lachezar
我要补充的是,let 会让你实现你在这里尝试的功能,但它还没有被广泛支持。 - arb
我认为"use strict"非常像一种反对语言特性。 为什么我们没有类似于"use local variables only"的东西呢? - anvoz
显示剩余2条评论
2个回答

2

你可以使用阴影变量。如果你在函数内部显式声明变量(而不初始化它),函数将使用此变量,而不是外部作用域中同名的变量。

例如:

var outer = 'foo';

function isolated () {
  var outer;
  console.log(outer);
};

isolated(); // output undefined

这应该能满足你的需求。

还有另一种方法,但它是一种丑陋的黑客方式,可能在某些浏览器上无法工作(IE?)。

以下是一个示例:

var outer = 'foo';

function isolated () {
  console.log(outer);
};

var e = eval;
// will throw exception: 'outer' is not defined
console.log(e('('+isolated.toString()+')()'));

evale并不完全相同。'真正的' eval可以访问整个作用域,但如果你复制它,那么JavaScript引擎可以通过不使外部作用域可用于被评估的代码来进行优化。

然而:不要这样做

  • 首先:它依赖于函数.toString()将输出函数的代码。这不是规范的一部分,因此不可靠(虽然在v8和spidermonkey上有效)。
  • 其次:eval应该避免使用,它会使调试变成噩梦(您无法访问有用的堆栈跟踪),存在性能和安全问题,并且您很快就会得到一个难以维护的糟糕代码。

+1 但这些会大大改变我的源代码。目前我还可以接受语言本身仍然不允许您在没有任何黑客攻击的情况下隔离函数范围的事实。 - anvoz

0

不知道你为什么想这样做,但是使用这个简短的例子:

(function(theFunk) {
    var world = new World(),
        Event = world.Event,
        Guide = world.Guide;

    Event.add('updateUI',theFunk);

})(function(){
        this.Guide.show('UI updated');  // 1st: depends on what you do with it
        world.Guide.show('UI updated'); // 2nd: will fail (depends on global)
        Guide.show('UI updated');       // 3rd: will fail (depends on global)
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接