在javascript中,是访问';window.Math';比访问';数学';不带';窗口;?
我有点好奇在javascript中引用“全局”名称空间时的最佳实践是什么,它仅仅是在javascript中,是访问';window.Math';比访问';数学';不带';窗口;?,javascript,performance,window,global-variables,global,Javascript,Performance,Window,Global Variables,Global,我有点好奇在javascript中引用“全局”名称空间时的最佳实践是什么,它仅仅是窗口对象的快捷方式(反之则取决于您如何看待它) 我想知道: var answer = Math.floor(value); 好于或坏于: var answer = window.Math.floor(value); 在性能、资源使用或兼容性方面是更好还是更差,哪怕只是一点点 一个有稍微高一点的成本吗?(像一个额外的指针之类的东西) 编辑说明:虽然在大多数情况下,我的可读性高于性能,但在这种情况下,我忽略了可读性
窗口
对象的快捷方式(反之则取决于您如何看待它)
我想知道:
var answer = Math.floor(value);
好于或坏于:
var answer = window.Math.floor(value);
在性能、资源使用或兼容性方面是更好还是更差,哪怕只是一点点
一个有稍微高一点的成本吗?(像一个额外的指针之类的东西)
编辑说明:虽然在大多数情况下,我的可读性高于性能,但在这种情况下,我忽略了可读性的差异,只关注性能。不同浏览器的JS性能差异很大
我的建议是:对其进行基准测试。把它放在一个for循环中,让它运行几百万次,然后计时。。。。看看你得到了什么。一定要分享你的结果 首先,不要因为性能原因而比较这些东西
Math.round
显然比window.Math.round更容易观看,而且使用其中一种方法不会显著提高性能。因此,不要为了性能的微小提高而混淆代码
然而,如果你只是好奇哪一个更快。。。我不确定全局范围是如何“在引擎盖下”查找的,但我猜访问窗口
与访问数学
是一样的(窗口
和数学
处于同一级别,这可以从窗口.窗口.数学.圆形
工作中得到证明)。因此,访问window.Math
会更慢
此外,通过查找变量的方式,您将看到通过执行var round=Math.round
并调用round(1.23)
,因为所有名称首先在当前本地范围中查找,然后在当前范围上查找,依此类推,一直到全局范围。每个作用域级别都会增加非常小的开销
但同样,不要做这些优化,除非你确信它们会产生明显的变化。可读、可理解的代码对于it在现在和将来的工作方式都很重要
以下是使用Firebug的完整评测:
<!DOCTYPE html>
<html>
<head>
<title>Benchmark scope lookup</title>
</head>
<body>
<script>
function bench_window_Math_round() {
for (var i = 0; i < 100000; i++) {
window.Math.round(1.23);
}
}
function bench_Math_round() {
for (var i = 0; i < 100000; i++) {
Math.round(1.23);
}
}
function bench_round() {
for (var i = 0, round = Math.round; i < 100000; i++) {
round(1.23);
}
}
console.log('Profiling will begin in 3 seconds...');
setTimeout(function () {
console.profile();
for (var i = 0; i < 10; i++) {
bench_window_Math_round();
bench_Math_round();
bench_round();
}
console.profileEnd();
}, 3000);
</script>
</body>
</html>
正如您所看到的,window.Math
是一个非常糟糕的主意。我猜访问全局窗口对象会增加额外的开销。但是,从全局范围访问Math
对象与仅通过引用Math.round
函数访问局部变量之间的区别不是很大。。。请记住,这是100000次呼叫,差异仅为3.6ms。即使有一百万个电话,你也只能看到36毫秒的差异
使用上述分析代码需要考虑的事项:
- 这些函数实际上是从另一个作用域中查找的,这增加了开销(尽管我尝试将函数导入到匿名函数中,但几乎没有注意到)李>
- 实际的
Math.round
函数增加了开销(我估计100000次调用中大约有6ms)
如果在本地/函数范围内调用Math.round()
,解释器必须首先检查本地变量,然后在全局/窗口空间中检查。所以在局部范围内,我猜测window.Math.round()
会稍微快一点。这不是程序集,或者C或C++,所以我不会担心哪一个更快,因为性能原因,但是如果出于好奇,确定,基准。p> (正如您所说)Math.floor
可能只是大多数Javascript实现(如V8)中window.Math
(因为window
是一个Javascript全局对象)的快捷方式
Spidermonkey和V8将针对常见用途进行大量优化,因此不应担心
为了可读性,我更喜欢使用Math.floor
,速度上的差异将非常小,不值得担心。如果您正在进行100000层的测试,那么可能是时候将该逻辑从客户机中切换出来了
您可能想了解一下v8源代码,这里有一些有趣的评论,关于减少函数的纳秒数,例如int.Parse()
one
// Some people use parseInt instead of Math.floor. This
// optimization makes parseInt on a Smi 12 times faster (60ns
// vs 800ns). The following optimization makes parseInt on a
// non-Smi number 9 times faster (230ns vs 2070ns). Together
// they make parseInt on a string 1.4% slower (274ns vs 270ns).
如果您想知道流程是如何工作的,这可能是一个有趣的问题
范围链是在计算标识符时搜索的对象列表,代码无法访问这些对象,只能访问其属性(标识符)
首先,在全局代码中,范围链被创建并初始化为只包含全局对象
链中的后续对象是在函数执行上下文中输入时创建的,通过with
语句和catch
子句也将对象引入链中
例如:
// global code
var var1 = 1, var2 = 2;
(function () { // one
var var3 = 3;
(function () { // two
var var4 = 4;
with ({var5: 5}) { // three
alert(var1);
}
})();
})();
在上述代码中,如果使用var1
或var2
变量,范围链将包含不同级别的不同对象,例如,在with
语句中的最低级别,范围链将包含4个需要检查以获取标识符的对象:由with
语句引入的对象、两个函数,最后是全局对象
您还需要知道window
只是全局对象中存在的一个属性,它指向全局对象本身<代码>窗口
由浏览器引入,在其他环境中通常不可用
总之,当您使用window
时,由于它只是一个标识符(不是保留字或类似的东西),并且需要通过所有解析过程才能获得全局对象,window.Math
需要一个由t
// global code
var var1 = 1, var2 = 2;
(function () { // one
var var3 = 3;
(function () { // two
var var4 = 4;
with ({var5: 5}) { // three
alert(var1);
}
})();
})();