只有在ES5严格不存在的情况下才能定义全局变量?

时间:2012-10-11 22:27:59

标签: javascript ecmascript-5

我正在ES5中编写ES Harmony Symbol / Name的实现。我将使用名称Symbol,但我希望浏览器使用它已存在的任何预先存在的Symbol(在将来的浏览器中)。我希望我的代码符合ES5严格要求并可移植到其他项目中。

这是(非常多的)在ES3 / ES5非严格中做我想做的一种方式:

(function() {

    // If Symbol already exists, we're done.
    if(typeof Symbol != 'undefined') return;

    // This becomes global because it wasn't declared with var
    Symbol = function() {
        // ...
    };

})();

但是,由于Symbol未明确定义,因此不符合ES5标准。

实现此目的的其他方法包括访问window对象(window.Symbol = ...),但这也不好,因为我不希望我的代码假设它在浏览器环境中运行。 / p>

如何在严格的ES5中完成?

4 个答案:

答案 0 :(得分:4)

其他用户发布的答案让我得到了类似的StackOverflow问题,该问题为我提供了在Google中搜索以找到答案的正确条款。解决方案:

我最终能够使用indirect eval来解决这个问题,描述为here

使用上面链接的文章中详细介绍的间接评估,按照ES5规范在全局范围内执行代码。我选择采用这种方法,因为它符合ES5规范,它允许代码逐字地删除,甚至在包管理器的另一个函数内部,并且仍然可以找到全局对象(提供的其他答案无法做到。)

解决方案就是这样:

(function() {

    'use strict';

    var _global = (0, eval)('this');

    // If Symbol is already defined, there's nothing to do.
    if(_global.Symbol) return;

    _global.Symbol = function() {
        // ...
    };

})();

关键是使用间接eval在间接this的上下文中检索全局对象(eval)。

这应该适用于符合ES5标准的任何内容,包括现代浏览器和非浏览器环境,正如我所希望的那样。

感谢所有人的帮助!

唯一需要注意的是,为了访问全局对象,必须以这种间接方式(现在更糟糕)使用eval(这已经够糟糕了)似乎有点蠢蠢欲动。访问全局对象的global标识符或其他方法是否不在规范中?

答案 1 :(得分:1)

'use strict';

var Symbol = 1; // try to comment this line and run the script again

var Symbol = (function(Symbol) {


    if(typeof Symbol != 'undefined') return Symbol;

    Symbol = function() {
        // ...
    };

    return Symbol;

})(Symbol);

alert(typeof Symbol);

http://jsfiddle.net/f0t0n/yATJW/

'use strict';

(function(g) { // g is a global context (this passed)

    if(typeof g.Array != 'undefined') {
        return;
    }

    g.Array = function() {
        // ...
    };

    g.Array.prototype.foo = function() {
        console.log('bar');
    };
})(this);

console.log(this.Array);​

http://jsfiddle.net/f0t0n/prwaP/

答案 2 :(得分:1)

为什么需要使用匿名函数?

// assuming global context
if (typeof this.Symbol === 'undefined') {
    this.Symbol = function () {
        // ...
    };
}

或在函数中,按照here

所述传递this
(function (t) {
    if (typeof t.Symbol === 'undefined') {
        t.Symbol = function () {
            // ...
        };
    }
})(this);

答案 3 :(得分:1)

如何传递要将Symbol添加到的全局范围?

(function(global){
 if(typeof global.Symbol != 'undefined') return;

    // This becomes global because it wasn't declared with var
    global.Symbol = function() {
        // ...
    };

})(window);  

这会将其添加到窗口,但可能是其他范围或var。