Javascript 中的 var

Javascript 中的 var

MelonCard发布了一篇文章——”how one missing var ruined our launch“(”少写了一个var毁了我的网站”),这篇文章是说MelonCard用Node.js做后台,因为出了一个小高峰——有50-100人注册,结果整个网站都不响应了,而且还出现了很多奇怪的问题。当他们调查到问题的要源的时候,他们发现下面的代码少写了一个var。

[javascript]app.all(‘/apps/:user_id/status’, function(req, res, next) {
// …
initial = extractVariables(req.body);
});[/javascript]

为什么inital少写一个var会引发这个问题呢?因为如果你不写var,这个局部的变量会被javascript当成全局变量,而这个变量又是一个函数,所以,当多用户并发的时候,这个本应该在不同用户下互不干扰的变量,成了各个用户共享的东西。试想,用户A的数据被用户B覆盖了,用户A和B的数据还没处理完,结果被新的C给搞乱了,程序的逻辑自然出现了问题。

在stackoverflow.com上有这么一个贴子说明了“有var”和“无var”的差别:

// These are both globals
var foo = 1;
bar = 2;

function test()
{
    var foo = 1; // Local
    bar = 2;     // Global

    // Execute an anonymous function
    (function()
    {
        var wibble = 1; // Local
        foo = 2; // Inherits from scope above (creating a closure)
        moo = 3; // Global
    }())
}

上面这个示例告诉我们,如果你不用var,那么这个js引擎会一层一层地向上找父作用域中的变量,如果找到了,就用,如果找不到了,就会帮你定义一个全局的变量。上面这个例子充分说明了这一点。所以,如果你想在当前的作用域用声明变量,你一定要用var。这对于一些乱写javascript代码的程序员要注意了。这里再给大家介绍一个工具——

JSLint( http://www.jslint.com/ ),一个JS代码质量的分析工具,我们把上述stackoverflow的代码copy到JSLint这个在线工具中,我们可以看到下面的报告:

这个报告说明了源码中的那些变量的情况。

(全文完)

(转载本站文章请注明作者和出处 酷 壳 – CoolShell ,请勿用于任何商业用途)

好烂啊有点差凑合看看还不错很精彩 (16 人打了分,平均分: 3.94 )
Loading...

Javascript 中的 var》的相关评论

  1. 【这对于一些乱写javascript代码的程序员要注意了】
    设计语言的时候,为什么不尽量让人想乱写都无法乱写呢?

  2. @haitao
    十来天设计的语言……
    而且作者是研究函数式的,为了闭包总得找得到变量定义的地方,不写 var 就当成 local 的话就没闭包的事了。

  3. @enz

    coffee 没有var是个更大的问题。这样你程序本来是对的,某天碰巧在前面定义了一个全局变量,结果后面就自动错了,都没法指定成local的

  4. 关于这些东西,可以看《javascript语言精粹》这本书,大牛里面都说了这些东西的

  5. 这个貌似一般讲javascript语法的书中都提到要注意全局变量和局部变量,不过实际写的时候确实会偶尔犯这样的错误。

  6. 此外我有一点想吐槽楼主 – 也是整个 coolshell.cn 如果没记错 – 你们为神马要一个 IE=EmulateIE7? 在 IE 9/10 标准模式下效果更好哦。。。:)

  7. JavaScript坑爹的地方挺多,诘诎聱牙起来甚至有点像C++的语法了…所以现在做Node开发,开始流行用CoffeeScript来编写代码,再transcompile成JavaScript了…

  8. 类似的情况还有this关键字,写Java的时候习惯不用this获取成员变量,Javascript不用this获取的完全是不同的东西

  9. tlzebsl :@haitao 十来天设计的语言……而且作者是研究函数式的,为了闭包总得找得到变量定义的地方,不写 var 就当成 local 的话就没闭包的事了。

    严格点,应该:global声明的变量,是全局变量;var声明的是局部变量;没声明的语法报错。
    语言设计,真正是:严是爱,宽是害

  10. 一直没有遇到过这种问题,看来俺写代码的习惯还是不错的。由此可以看出良好的编码习惯是多么的重要啊!

  11. 半瓶墨水 :这是javascript的设计缺陷。
    应该设计成这样:默认变量是局部的,全局变量必须加上类似于global关键字的前缀。

    或者干脆学ruby那样,不同作用域的名称的命名方法有显式的区别…

  12. 其实不加var也可以呀
    主要不要共享此函数就好了
    initial = clone(extractVariables(req.body));
    足以,复制一个就行,保证不同,不共享,clone自写。。。复制一个对象

  13. 耗哥现在对JavaScript很感兴趣了呀,嗨,两年前我用js写的扫雷游戏就中了var的招了,在递归地扫描某个格子周围非地雷格子的函数中:

    function search_empty_square( square ) // first invoked with square.value == 0
    {
    // var sr ;
    if( square.value >=0 && square.locked == false ) {
    click_square( square ) ;
    if( square.value == 0 ) {
    if( square.x>0 && square.y>0 && !( sr=document.getElementById((square.x-1)*row+(square.y-1)) ).clicked )
    search_empty_square( sr ) ;
    if( square.x>0 && !( sr=document.getElementById((square.x-1)*row+square.y) ).clicked )
    search_empty_square( sr ) ;
    if( square.x>0 && square.y0 && !( sr=document.getElementById(square.x*row+(square.y-1)) ).clicked )
    search_empty_square( sr ) ;
    if( square.y<row-1 && !( sr=document.getElementById(square.x*row+(square.y+1)) ).clicked )
    search_empty_square( sr ) ;
    if( square.x0 && !( sr=document.getElementById((square.x+1)*row+(square.y-1)) ).clicked )
    search_empty_square( sr ) ;
    if( square.x<line-1 && !( sr=document.getElementById((square.x+1)*row+square.y) ).clicked )
    search_empty_square( sr ) ;
    if( square.x<line-1 && square.y<row-1 && !( sr=document.getElementById((square.x+1)*row+(square.y+1)) ).clicked )
    search_empty_square( sr ) ;
    }
    }
    }

    上述代码没有对sr进行var声明,导致sr成为全局变量了,之前用C++写的扫雷扫描算法是OK,移植到JavaScript就出问题了,当时还以为JavaScript不支持递归呢,最后看了《精通JavaScript》后才知道不使用var进行声明的变量会成为全局变量,自做完扫雷游戏开始,在每次变量使用前我都会用var进行声明,教训呀,

  14. node.js已经支持use strict了就是用来杜绝此问题的。
    给你找个特性了你不去用,那怪谁啊
    只要在文件头添加一行”use strict”;
    任何未声明的变量都会报错
    “use strict”;

    app = 1;//报错

    (function(){
    var local = 2;
    })();

  15. haitao :

    tlzebsl :@haitao 十来天设计的语言……而且作者是研究函数式的,为了闭包总得找得到变量定义的地方,不写 var 就当成 local 的话就没闭包的事了。

    严格点,应该:global声明的变量,是全局变量;var声明的是局部变量;没声明的语法报错。
    语言设计,真正是:严是爱,宽是害

    其实,这是js语言的一大优点,jsvascript根本就与严格语言没什么关系。扔掉那些诸如Fortran的规范语言,和面向对象的java语言后,再来学它。

    还有重要的一点,js本就不是为了生产而设计出来的语言。

  16. artair :

    haitao :

    tlzebsl :@haitao 十来天设计的语言……而且作者是研究函数式的,为了闭包总得找得到变量定义的地方,不写 var 就当成 local 的话就没闭包的事了。

    严格点,应该:global声明的变量,是全局变量;var声明的是局部变量;没声明的语法报错。语言设计,真正是:严是爱,宽是害

    其实,这是js语言的一大优点,jsvascript根本就与严格语言没什么关系。扔掉那些诸如Fortran的规范语言,和面向对象的java语言后,再来学它。
    还有重要的一点,js本就不是为了生产而设计出来的语言。

    @artair
    不为了生产?软件大了就如泥潭,不严格就更早、更快就变成泥潭。。。。。。。

  17. 这与运行时编译和运行前编译有关系,而且JavaScript也有他自己的故事,有兴趣可以看看道格拉思的写的那本书:JavaScript语言精粹。@haitao

  18. 在客户端虽然也有问题,但还不至于这么大。node js放在了客户端,确实把问题放大了……

  19. 刚刚碰到一个类似的问题,用 jQuery 生成 bootstrap alert,在 1.5 秒后自动消失。结果存在多个 alert 的时候,只有最近创建的那一个会正常消失。

    偶然看到这篇文章解决了,原因也是声明局部变量的时候没有写 var。多谢!

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注