某些浏览器本地全局对象是使用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
defined as an extern,但在与window
一起使用时仍会重命名。
答案 0 :(得分:1)
对此没有一个好的答案。
正如您所观察到的,在Closure-compiler默认externs中,一些对象被定义为窗口对象上的属性,一些被定义为全局对象,一些被定义为两者。确实没有充分的理由 - 只是外围人员就是这样开发的。默认的externs会随着时间的推移而发展,因此在开发人员需要时会添加定义,这些定义会开始解释当前的状态。
高度需要的任务是从已发布的IDL文档生成外部的方法。但是,这种更改可能会破坏现有代码(默认类型名称可能会略有变化),到目前为止还没有开发人员愿意承担这项任务。
更新注意:并不是真的希望将所有全局变量定义为window
上的对象和属性。这样的代码只会弹出默认外部的大小。但是,应该在两者上定义常用的外部。
鼓励开发人员使用VERBOSE
警告,以便编译器警告未定义的属性。
答案 1 :(得分:0)
没有区别。您需要了解的是JavaScript全局范围。
每当我尝试解析变量名称时,无论是什么,都会查找范围链。
想象一下你有这个:
function() {
var k = 5;
function() {
(function() {
k = 6;
})();
};
};
console.log(k);
正如您所看到的,放置它的位置并不重要,更高的订单定义是“记住的”,除非您手动覆盖它。
setTimeout
也是如此。无论您将setTimeout
放置在代码中的哪个位置,无论您嵌套多少次,JavaScript都会查找它并在window
中找到它,它会解析它。
无论您键入window.something
还是something
都没有区别,因为如果存在某些内容将在全局范围内解析,或者如果找不到则会抛出ReferenceError
。
Closure Compiler (以上与编译器的行为无关)。
Closure Compiler以这种方式是愚蠢的,至少从浅的角度来看。告诉它“不要碰这个属性”是不好的方法。
阻止属性重命名的简单方法是通过["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
,但不会触及实际名称。