【问题标题】:js: var declarations, loops, efficiency, utilityjs:var 声明、循环、效率、实用程序
【发布时间】:2011-08-28 08:53:36
【问题描述】:

除了可读性... 就效率和/或功能而言,我不清楚将声明放置在外部(我的实践)或循环内部(在其他 SO 帖子中看到)之间的区别。或者就此而言,为什么要代码声明?这里有一些退化的例子......下面还有更多的 cmets。

A1:

var x;
for (i=0; i<10; i++){
    x = i;
 }

A2:

for (i=0; i<10; i++){
    var x = i;
 }

B1:

var i;
for (i=0; i<10; i++){
 }

B2:

for (var i=0; i<10; i++){
 }

C1:

var x;
var y;

C2:

var x, y;

除了可读性... 我怀疑 B1 和 B2 之间以及 C1 和 C2 之间没有区别,但对 A1 和 A2 之间的效率或功能差异持怀疑态度。另外,除了在函数中使用声明来消除(?)与同名全局变量的可能冲突之外,我不确定声明有什么优势。

编辑:添加了几个分号

编辑:第一句清晰,将功能更改为功能

编辑:在下面添加一些代码以帮助我在下面发表评论 编辑:cmets

<!doctype html>
<html>
<head>
<script type='text/javascript'>
var w = (function(){  // wrapper
    alert('init');
    function p(){ // private
        alert('p');
        w.b(); //needs prefix
    }
    return{
        a: function(){ // public
            alert('a'); 
            p();
            w.b(); // needs prefix 
        },
        b: function(){ // public
            alert('b'); 
        }
    };
})(); // execute immediately
</script>
<script type="text/javascript">window.onload=w.a;</script>
</head>
<body>
sequence of alerts will be 'init' 'a' 'p' 'b'
</body>
</html>

【问题讨论】:

    标签: javascript performance variables declaration utility


    【解决方案1】:

    变量声明被提升到函数的顶部。这不会有任何区别,除非您当然是在谈论在新函数范围内声明变量。


    编辑:一开始没有注意到,你的第一个例子没有用var声明i。这不是好的做法。


    编辑:

    通常最好避免创建全局变量,以避免与可能设置全局变量的其他脚本发生冲突。

    每当您使用一个变量而不用var 声明它时,它就会变成全局变量。

    在 JavaScript 中创建新变量范围的唯一方法是在函数体中。函数可以相互嵌套,创建一个范围链,从最里面的函数开始,到全局范围结束。

    因此,通常将所有代码放在一个立即调用的函数中。这样,您使用 var 创建的任何变量都不会成为全局变量。

    (function() {   // <-- create a function
    
        // place your code in here
    
          // use "var" when declaring variables so they don't become global
        var name = "patrick dw";
    
        alert( name );
    
    })(); // <-- invoke the function immediately so your code runs
    

    在前面的示例中,name 变量对于立即调用的函数来说是本地的,不会污染全局范围。

    因为遍历变量作用域需要一些资源,所以人们在调用该函数时通常会传入一些参数,例如window

    (function( window, undefined ) {
    
          // now the window object is referenced locally. Better for performance.
    
        var name = "patrick dw";
    
        alert( name );
    
    })( window ); // <-- invoke the function passing in the global "window" object
    

    现在window 对象在您的函数内部被本地引用,因此如果您访问window 的某些属性,它就不必一直跟随您的函数外部的范围链。

    我还在函数中包含了一个额外的undefined 参数,但没有将参数传递给它。这是为了帮助避免一些不良编码实践带来的奇怪问题。但这是另一个问题。

    现在采用相同的函数,如果我们在声明name 变量时不使用var,它将自动成为全局变量。我将更新示例,并添加另一个函数范围来说明。

    (function( window, undefined ) {
    
              // create a function 
        function some_func() {
    
            name = "patrick dw";  // didn't use "var" when declaring!!
            alert( name );
        }
    
        some_func();  // call our function
    
        alert( window.name ); // but "name" is also accessible from the global window
    
    })( window );
    
    alert( name ); // outside those functions, we're global, and again we can see that
                   //   the "name" variable is accessible
    

    如您所见,我们从未声明过var name,因此它变成了一个自动全局变量,即使它嵌套了两个函数。

    这是许多错误的根源,也是您在使用var 时需要格外小心的原因。


    最后,我要指出的是,当您在 "strict mode"; 中运行代码时,ECMAScript 5 不允许一些不良的编码做法。目前没有多少浏览器实现strict mode,但在其中经常测试您的代码会很有帮助。

    Here's a compatibility table for ECMAScript 5。严格模式在底部。你会看到 Firefox 4 支持它。

    这是一个例子:

    (function( window, undefined ) {
    
        "strict mode"; // <-- use the strict mode directive
    
        name = "patrick dw";  // In Firefox 4, you should get a ReferenceError in the console
                              //   because "name" was never declared with "var"
    })( window );
    

    【讨论】:

    • @patrick - 以下是否正确?假设 x 在某个函数中没有声明就被编码。 js 编译器将首先查看 x 是否存在于更广泛的命名空间中。如果在更广泛的命名空间中找到,则编译器将 x 实现为找到的那个。另一方面,如果在更广泛的命名空间中找不到,那么编译器会将 x 指定为函数命名空间中的新变量?
    • @mike:不。首先,准确地说,我们应该将其称为 scope 而不是 namespace。变量作用域是在函数中创建的,函数可以嵌套。还有默认的全局范围。如果x 已在当前函数范围内声明,则将使用它。如果没有,它将搜索外部范围以查看它是否已被声明。如果它没有在任何范围内声明,该变量将被添加到 global 范围内,而不是当前函数。因此,明确定义声明变量的范围非常重要。
    • ...通常情况下,根本不使用全局变量被认为是一种好习惯,或者如果您需要将某些方法或数据公开给正在执行的其他 javascript,则最多只使用一个。这很容易通过将您的代码放在一个立即执行的函数中来完成:(function() { /* all your code */ })()。然后确保在适当的位置使用var 声明变量。我会用一些例子来更新我的答案。
    • @patrick - 谢谢...哎呀! re: '如果没有在任何范围内声明,该变量将被添加到全局范围内'
    • 我有一个会议......早在 90 年代
    【解决方案2】:

    这只是语法差异。我认为即使在 B 两个声明都在同一范围内。

    只声明 i 不带 var 将导致它在全局范围内定义。

    这主要是关于哪种选项最适合情况,同时仍应尽可能保持一致。

    如果您已经有一个全局变量 x,我认为这不会阻止冲突。

    【讨论】:

    • "...在没有 var 的情况下声明 i" 根据定义是不可能的。未声明的变量在它们第一次被赋值时(即它们被初始化时)成为全局对象的属性。
    • 混淆了声明和初始化
    【解决方案3】:

    使用var时,javascript变量的作用域与整个函数共享,因此A1和A2都在一个函数中时不会有任何区别。

    但是,您可以使用 let 关键字并将变量范围限制为块,例如:

    for(let x = 0; x < 10; x++){}
    

    这会将 x 变量限制为仅在 for{} 块内具有范围。

    【讨论】:

    • 还有一个类似的问题,我只是忘了在这里链接:stackoverflow.com/questions/790558/…
    • let 没有被广泛使用,也不是任何当前标准的一部分,尽管它应该会出现在下一版本的 ECMAScript 中。
    【解决方案4】:

    A1 或 A2 之间也没有功能或效率差异。试试这个:

    var arr=[];
    for(var i=0; i<10; ++i) {
      var x=i;
      arr.push( function() {alert(x);} );
    }
    for(var i=0; i<10; ++i) {
      arr[i]();
    }
    

    您会看到所有函数显示的值都是相同的,因为所有函数都使用相同的 x。不是每次都创建新变量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-26
      • 2013-04-18
      • 2013-09-04
      • 2014-03-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多