Javascript 以严格模式在未知环境中获取对全局对象的引用

Javascript 以严格模式在未知环境中获取对全局对象的引用,javascript,global,ecmascript-5,ecma262,strict-mode,Javascript,Global,Ecmascript 5,Ecma262,Strict Mode,在未知主机环境中,在ES5严格模式下获得的句柄的推荐方法是什么 ECMAScript没有提供一种内置的方式来引用我所知道的全局对象。如果是的话,这就是我想要的答案 在已知环境中,全局对象通常具有自引用属性。由于全局对象是全局作用域的句柄,因此全局对象的属性是全局变量,因此我们可以使用它们从任何位置获取全局对象的句柄: 在web浏览器中,我们可以使用window或self 在node.js中,我们可以使用global 但是,并非所有主机环境都是如此。据我所知,Windows脚本主机不提供任何访

在未知主机环境中,在ES5严格模式下获得的句柄的推荐方法是什么

ECMAScript没有提供一种内置的方式来引用我所知道的全局对象。如果是的话,这就是我想要的答案

在已知环境中,全局对象通常具有自引用属性。由于全局对象是全局作用域的句柄,因此全局对象的属性是全局变量,因此我们可以使用它们从任何位置获取全局对象的句柄:

  • 在web浏览器中,我们可以使用
    window
    self

  • 在node.js中,我们可以使用
    global

但是,并非所有主机环境都是如此。据我所知,Windows脚本主机不提供任何访问全局对象的方法。在WSH中获取全局对象的推荐方法似乎是在不解析为对象的上下文中使用
this
关键字。例如:

var GLOBAL = (function(){return this}());
此技术适用于任何主机环境,但不适用于严格模式,因为未定义的
This
不会引用以下环境中的全局对象:

如果在严格模式代码中对此进行求值,则不会将此值强制为对象A此null或undefined值不会转换为全局对象,并且原语值不会转换为包装器对象。通过函数调用传递的此值(包括使用function.prototype.apply和function.prototype.call进行的调用)不会强制将传递的此值传递给对象(10.4.3、11.1.1、15.3.4.3、15.3.4.4)

正如预期的那样,以下代码会导致
未定义

(function(){
    "use strict";
    var GLOBAL = (function(){return this}());
    console.log(GLOBAL);
}());

那么,在任何环境中,无论严格模式如何,获得全局对象句柄的正确方法是什么

顺便说一下,我当前的方法是嗅探引用全局对象的全局变量,如下所示:

var self, window, global = global || window || self;

…然后只需使用
global
。我认为这是一个糟糕的解决方案,原因有很多,其中大多数是相当明显的,并且它没有解决WSH问题。

在严格模式下,获取全局对象引用的方法是在全局对象引用自身中分配一个变量

也就是说,解决方案很简单:

"use strict";
var global = global || this;
(function() { global.hello = "world"; })();
console.log(hello); // Outputs 'world' as expected

这意味着您必须使用对自身的引用来污染全局名称空间,但正如您所说,它应该已经存在了。

在ES5中,您可以通过间接求值调用从严格模式中获得对全局对象的引用:

"use strict";
var global = (1,eval)('this');
看一看,;尤其是在这种情况下。

在中,
thisBinding
被设置为全局对象,而与严格模式无关。这意味着您可以将其传递到您的模块IEFE:

// "use strict"; or not
(function(global) {
    "use strict";
    …
    console.log(global);
    …
}(this));

Mathias Bynens有一篇关于这个主题的优秀文章。以下内容适用于所有环境,
使用严格的
或否,包括启用CSP的环境,如Chrome扩展

(函数(){
//一个球体这个多边形填充物改编自https://mathiasbynens.be/notes/globalthis
if(typeof window!=='undefined'&&window&&window.window===window){return window}//所有浏览器
else{//webworkers,或服务器端Javascript,如Node.js
试一试{
Object.defineProperty(Object.prototype,“\uuuuu magic\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
get:function(){
归还这个;
},
可配置:true//这使得以后可以“删除”getter
});
__魔幻世界这是魔幻世界;
删除Object.prototype.\uuuuu magic\uuuuuuu;
回归全球;
}捕获(e){
//我们不应该到这里,因为我所知道的所有服务器端JS环境都支持Object.defineProperty
return(typeof globalThis==='object')?globalThis:((typeof global=='object')?global:this);
}
}
})();

你不能“严格使用”吗;(函数(全局){})(此)
?(我没有做任何测试)。这至少在Node.js中是有效的@Marshall@DavidEllis呜呜,这是我选择的平台,我想我应该在说之前先在别人那里查一下;)@马歇尔,对不起,如果你对我说的话感到困惑。我刚刚在Node.js中测试过,这就是我的意思;仅此而已。我假设它可以在Firefox和IE中运行,但我不确定这个Windows脚本主机环境(Metro是为基于HTML的应用程序运行的吗?@Marshall)应该可以在浏览器中运行,但这意味着我的代码需要能够在全局范围内运行。你能解释一下node.js是如何工作的吗?我的理解是,
this
解析为node.js脚本“module scope”中的
module
对象,那么您的匿名函数不应该只返回该
module
对象吗?(我对node只有理论上的理解,而不是实际的理解)。谢谢你的回复,我已经读了你的许多文章(顺便说一下,这些文章很好),但我一定错过了这篇。我考虑过使用
eval
,但不知道这个间接技巧(显然,只使用
eval
而不在函数范围内进行间接计算)。谢谢你的好话:)说到eval技巧,我听说Node.js在这方面没有遵循ES5的行为,而且在幕后还有一些其他的魔力。从来没有机会测试它,所以你可能想再检查一遍。不过,它在我尝试过的所有浏览器中都可以工作,而且理论上应该可以工作,因为ES5中就是这样规定的。我将在node中测试它。。。如果它在节点中被破坏,我可以让它检查已经存在的
global
来解决这个问题(并将示例中的
global
重命名为其他名称,这样如果从函数范围调用它,它就不会对现有的
global
产生阴影)。这正是我想要的