5

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

这是在 ES3/ES5 non-strict 中做我想做的事情的一种方法:

(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() {
        // ...
    };

})();

但是,它不是 ES5 严格兼容的,因为Symbol没有明确定义。

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

如何在 ES5 严格中做到这一点?

4

4 回答 4

4

其他用户发布的答案将我引向了一个类似的 StackOverflow 问题,该问题为我提供了在 Google 中搜索以找到答案的正确术语。解决方案:

我最终能够使用此处描述的间接评估来解决这个问题。

根据 ES5 规范,使用上面链接的文章中详细介绍的间接 eval会在全局范围内执行代码。我选择采用这种方法,因为它符合 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访问全局对象的标识符或其他方法是否应该不在规范中?

于 2012-10-12T04:03:24.337 回答
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);

​</p>

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/

于 2012-10-11T22:29:45.437 回答
1

为什么它需要在匿名函数中?

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

或在函数中,this此处所述传递

(function (t) {
    if (typeof t.Symbol === 'undefined') {
        t.Symbol = function () {
            // ...
        };
    }
})(this);
于 2012-10-11T22:32:55.137 回答
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。

于 2012-10-11T22:33:40.063 回答