Refresh

This website coolshell.cn/articles/7480.html is currently offline. Cloudflare's Always Online™ shows a snapshot of this web page from the Internet Archive's Wayback Machine. To check for the live version, click Refresh.

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。多谢!

发表回复

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