3

一些浏览器原生的全局对象是用window和其他的不写的。

window.setTimeout
window.getComputedStyle
JSON
decodeURIComponent

为什么?有什么不同?这true适用于所有情况。

'setTimeout' in window
'getComputedStyle' in window
'JSON' in window
'decodeURIComponent' in window

在使用Closure Compiler时,我首先注意到一个明显的区别。

输入

// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @output_file_name default.js
// @formatting pretty_print
// ==/ClosureCompiler==

window.decodeURIComponent;
window.getComputedStyle;
window.setTimeout;
window.JSON;
decodeURIComponent;

输出

window.a;
window.getComputedStyle;
window.setTimeout;
window.JSON;
decodeURIComponent;

它已decodeURIComponent 定义为 extern,但在与 一起使用时仍将其重命名window

4

2 回答 2

1

对此没有很好的答案。

正如您所观察到的,在 Closure-compiler 默认 externs 中,一些对象被定义为窗口对象的属性,一些被定义为全局对象,还有一些两者兼而有之。这真的没有很好的理由——只是外部人员是这样开发的。默认外部变量随着时间的推移而演变,因此在开发人员需要时添加定义,从而开始解释当前状态。

一个非常需要的任务是从已发布的 IDL 文档中生成外部的方法。但是,此更改可能会破坏现有代码(默认类型名称可能会略有更改),并且迄今为止还没有开发人员愿意承担这项任务。

更新说明:将所有全局变量定义为对象以及window. 这样的代码只会膨胀默认外部的大小。但是,应该在两者上定义常用的外部变量。

鼓励开发人员使用VERBOSE警告,以便编译器对未定义的属性发出警告。

于 2013-05-02T12:52:35.397 回答
0

没什么区别。您必须了解的是 JavaScript 全局范围。

每当我尝试解析变量名时,无论它是什么,都会查找范围链。

想象一下你有这个:

function() {
    var k = 5;
    function() {
        (function() {
           k = 6;
        })();
    };
};
console.log(k);

如您所见,放置它的位置并不重要,“记住”更高阶的定义,除非您手动覆盖它。

也一样setTimeout。无论您将setTimeout代码放在哪里,无论您嵌套多少次,JavaScript 都会查找并找到它,window然后它会这样解析它。

无论您是键入window.something还是something因为某些东西如果存在或将抛出一个ReferenceError如果从未找到,它将在全局范围内解决,这没有区别。

闭包编译器(以上与编译器的行为无关)。

闭包编译器在这方面是愚蠢的,至少从肤浅的角度来看是这样。告诉它“不要碰这个属性”并不是一个好方法。

防止属性重命名的简单方法是通过["property"]. 请允许我演示一下:

var a = {};
a["bla"] = "bla";// compiler will not touch this.
a.bla2 = "bla2"l;// compiler will flatten this!!

但是您必须记住始终通过 访问该属性a["property"],否则您的调用a.property将被重写a.ab或其他任何内容并失败!

所以现在你需要window["decodeUriComponent"],一切都会好起来的。尽管它很奇怪,但这是最简单的技巧。编译器会将上述内容转换为window.decodeUriComponent,但不会触及实际名称。

于 2013-05-01T22:28:59.060 回答