Javascript中的评估顺序是顺序的吗?

时间:2013-01-31 20:07:58

标签: javascript

在求职面试中,我很难听到“javascript可以无序评估陈述”。这到底是什么程度的?我可以想象一百种方法来明确地无序地评估语句 - 例如在分时操作系统中。但他似乎说,如果我评价

console.log('a')
console.log('b')

Javascript规范以某种方式不要求输出先是a然后b。我可以想象,如果语句在功能上是纯的,即没有副作用,但是副作用必须始终按顺序发生,那么评估者可能尝试来评估第二个语句?当然,IO是一个很大的副作用。

规范兼容的Javascript在多大程度上可以无序评估?或者这是一个误传的情况?

4 个答案:

答案 0 :(得分:7)

JavaScript是单线程的(除了Web工作者)。期。 ECMA-262 Language Specification Edition 5.1没有提到无序执行。在您的简单示例中,这两个语句保证以相同的顺序执行。

此外,单个JavaScript代码块永远不会被任何其他代码块中断,例如事件处理程序这就是为什么长时间运行的代码块会导致UI 冻结

for(var i = 0; i < 1000000000; ++i) {
    console.log(i);
}

保证上面的代码块永远不会被中断或重新排序。只要循环正在运行,所有事件处理程序和超时都等待单个线程。当然,数字会以正确的顺序出现。

可能无序执行的是异步超时:

setTimeout(function() {
    console.log('a');
}, 1);
setTimeout(function() {
    console.log('b');
}, 1);

在这里,您可能希望首先打印a,但JS引擎可能会重新排序这些事件。毕竟你安排这些调用几乎在同一时间点执行。

答案 1 :(得分:2)

显然是误传。

这个家伙可能指的是JavaScript吊装。您可以在此处详细了解:http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

此外,您可以在此处了解该语言的更多特性:http://bonsaiden.github.com/JavaScript-Garden/

答案 2 :(得分:1)

在大多数情况下,是的。有两个主要的例外(撇开明显的“定义函数,调用函数”,它有效地“返回”函数体):

1:吊装。 var语句被悬挂,所以如果你写

alert(a);
var a = 123;

您获得undefined,而不是错误消息。这是因为它被提升到了

var a;
alert(a);
a = 123;

同样,函数定义也被提升。如果你写:

foo(123);
function foo(num) {alert(num);}

它会起作用,因为该功能是悬挂的。但是,如果你写了

,这不起作用
foo(123);
foo = function(num) {alert(num);}

因为这是一个匿名函数的赋值,而不是函数定义。

2:异步功能。

初学者的一个常见错误是写下这个:

var a = new XMLHttpRequest();
a.open("GET","sompage.php",true);
a.onreadystatechange = function() {
    if( a.readyState == 4 && a.status == 200) {
        myvar = "Done!";
    }
};
a.send();

alert(myvar);

他们希望警报说Done!,但是他们会因为没有被定义而得到一个莫名其妙的错误。这是因为myvar = "Done!"尚未运行,尽管在剧本中较早出现。


另见Computer Stupidities的这个轶事:

  

一位入门编程学生曾经让我看看他的程序,并弄清楚为什么它总是因为简单的计算而产生零。我查看了该程序,这很明显:

begin
 readln("Number of Apples", apples);
 readln("Number of Carrots", carrots);
 readln("Price for 1 Apple", a_price);
 readln("Price for 1 Carrot", c_price);
 writeln("Total for Apples", a_total);
 writeln("Total for Carrots", c_total);
 writeln("Total", total);
 total := a_total + c_total;
 a_total := apples * a_price;
 c_total := carrots + c_price;
end;
     
      
  • 我:“好吧,你的程序在计算之前无法打印出正确的结果。”
  •   
  • 他:“嗯?合适的解决方案是合乎逻辑的,计算机应该以正确的方式重新排列指令。”
  •   

答案 3 :(得分:0)

我认为他们试图让你走错了路。 Javascript是有序的。否则计算值的函数将无效。可能是真的是console.log激活Async task,这意味着它可以以不同的顺序执行。与Ajax来电相似,可以是Webworkertimeoutinterval

如果你执行以下操作,它将导致B而不是A,这不是一个顺序代码,因为在代码中。 A代表B,但B先执行。

setTimeout(function(){
    console.log("A")
}, 5);
console.log("B");