Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/474.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在javascript中,是访问';window.Math';比访问';数学';不带';窗口;?_Javascript_Performance_Window_Global Variables_Global - Fatal编程技术网

在javascript中,是访问';window.Math';比访问';数学';不带';窗口;?

在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); 在性能、资源使用或兼容性方面是更好还是更差,哪怕只是一点点 一个有稍微高一点的成本吗?(像一个额外的指针之类的东西) 编辑说明:虽然在大多数情况下,我的可读性高于性能,但在这种情况下,我忽略了可读性

我有点好奇在javascript中引用“全局”名称空间时的最佳实践是什么,它仅仅是
窗口
对象的快捷方式(反之则取决于您如何看待它)

我想知道:

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