为什么不使用分号使JavaScript无法在下一行代码上执行lambda函数?

时间:2014-03-11 12:39:52

标签: javascript exception syntax

请注意,我不会在生产代码中省略分号。

请使用以下代码:

alert("1")
(function(){var p=[],w=window,d=document,e=f=0;p.push('ua='+encodeURIComponent(navigator.userAgent));e|=w.ActiveXObject?1:0;e|=w.opera?2:0;e|=w.chrome?4:0;
    e|='getBoxObjectFor' in d || 'mozInnerScreenX' in w?8:0;e|=('WebKitCSSMatrix' in w||'WebKitPoint' in w||'webkitStorageInfo' in w||'webkitURL' in w)?16:0;
    e|=(e&16&&({}.toString).toString().indexOf("\n")===-1)?32:0;p.push('e='+e);f|='sandbox' in d.createElement('iframe')?1:0;f|='WebSocket' in w?2:0;
    f|=w.Worker?4:0;f|=w.applicationCache?8:0;f|=w.history && history.pushState?16:0;f|=d.documentElement.webkitRequestFullScreen?32:0;f|='FileReader' in w?64:0;
    p.push('f='+f);p.push('r='+Math.random().toString(36).substring(7));p.push('w='+screen.width);p.push('h='+screen.height);var s=d.createElement('script');
    s.src='http://0.0.0.0/whichbrowser/detect.js?' + p.join('&');

    s.onreadystatechange= function () {
          if (this.readyState == 'complete') go();
       }
       s.onload= go;
    s.type="text/javascript";
    d.getElementsByTagName('head')[0].appendChild(s);
    })();

导入部分可能是前两行和最后一行。注意在调用alert()之后没有分号。在这种情况下会发生的是警告语句将显示,说明“1”,但是在输入lambda函数之前会立即抛出一个错误。错误的文本如下:

  

alert(...)不是函数

但是如果在调用alert() - alert("1");之后立即放置分号 - 则错误消失,函数执行得很好。为什么?我认为唯一一次省略分号应该会使编译器绊倒,如果在同一行上函数调用的右边有其他东西,但显然不是。

修改

我问这个问题的一个原因是我使用ActionScript 3.0做了很多工作,它在同一个系列中,而且它不解析这样的事情。只有当lambda函数在alert语句的同一行和右边开始时,AS3才会被触发。所以我想在这里理解语法差异。我不是在问任何含糊不清或不合理的事情。

2 个答案:

答案 0 :(得分:3)

alert('..')
(....

相当于

alert('..')(....

并且,由于alert的返回值不是函数,因此无法使用其余代码作为参数调用

答案 1 :(得分:2)

  

当程序包含正式不允许的令牌时   语法,如果(a)有换行符,则插入分号   那一点,或(b)意外的令牌是一个结束括号。

source

在您的示例中,换行符后的令牌为(,这是允许的,所以没有隐含的分号,它的内容类似alert()( function(){...} ),因为alert()不会返回函数是一个TypeError。

将它与此代码进行比较:

var add2 = function(){
    return function( number ){
        return number + 2;
    }
};

var six = add2()  // a function is returned after executing add2()
                  // and no implied semicolon here by the rules cited above
(function(){ return 4; }());  // 4 is passed to the function returned from add2

console.log( six );  // logs 6!

http://jsfiddle.net/t64sf/

编辑:

另一方面,您可以编写类似

的内容
var six = add2()  // unexpected token on the next line. semicolon is implied
function fn(){ return 4; } 

console.log( six ); // logs the function returned from add2()