简体   繁体   English

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

[英]Is order of evaluation sequential in Javascript?

At a job interview, I was perplexed to hear "javascript can evaluate statements out of order." 在求职面试中,我很难听到“javascript可以无序地评估陈述”。 To what degree is this true? 这到底是什么程度的? I can imagine a hundred ways to explicitly evaluate statements out of order -- such as in a time-sharing operating system. 我可以想象一百种方法来明确地无序地评估语句 - 例如在分时操作系统中。 But he seemed to say that if I evaluate 但他似乎在说,如果我评估

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

that the Javascript spec somehow doesn't require that the output would be a first then b . 该规范的Javascript不知何故不要求输出将是a首接着b I can imagine that the evaluator might try to evaluate the second statement if the IO of the first is blocking if the statements are functionally pure, ie no side effects, but side effects must always occur in sequence, correct? 我可以想象,如果语句在功能上是纯的,即没有副作用,但副作用必须始终按顺序发生,那么评估者可能会尝试评估第二个语句,如果第一个语句的IO是阻塞的,那么正确吗? And of course IO is one big side effect. 当然,IO是一个很大的副作用。

To what extent can spec-compliant Javascript evaluate out of order? 规范兼容的Javascript在多大程度上可以无序评估? Or was this a case of miscommunication? 或者这是一个误传的情况?

JavaScript is single threaded (web workers aside). JavaScript是单线程的(除了Web工作者)。 Period. 期。 ECMA-262 Language Specification Edition 5.1 says nothing about out-of-order execution. ECMA-262语言规范版5.1没有说明无序执行。 In your simple example these two statements are guaranteed to be executed in the same order. 在您的简单示例中,这两个语句保证以相同的顺序执行。

Moreover, single block of JavaScript code will never be interrupted by any other block of code, eg event handler. 此外,单个JavaScript代码块永远不会被任何其他代码块中断,例如事件处理程序。 That's why long running blocks of code cause UI to freeze : 这就是长时间运行的代码块导致UI 冻结的原因:

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

It's guaranteed that the block of code above will never be interrupted or reordered. 保证上面的代码块永远不会被中断或重新排序。 As long as the loop is running, all event handlers and timeouts wait for single thread. 只要循环正在运行,所有事件处理程序和超时都等待单个线程。 And of course, numbers will appear in correct order. 当然,数字将以正确的顺序出现。

What might be executed out-of-order is an asynchronous timeout: 可能无序执行的是异步超时:

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

Here you might expect a to be printed first, but it's possible that JS engine will reorder these events. 在这里,你可能会想到a首先要打印出来,但它可能是JS引擎将重新安排这些活动。 After all you schedule these calls to execute at almost the same point in time. 毕竟,您安排这些调用几乎在同一时间点执行。

Clearly miscommunication. 显然是误传。

The dude was maybe referring to JavaScript hoisting. 这个家伙可能指的是JavaScript吊装。 You can read more about it here : http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting 你可以在这里阅读更多相关信息: http//www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

Furthermore, you can learn more particularities of the language here: http://bonsaiden.github.com/JavaScript-Garden/ 此外,您可以在此处了解该语言的更多特性: http//bonsaiden.github.com/JavaScript-Garden/

For the most part, yes. 多半是对的。 With two major exceptions (leaving aside the obvious "define a function, call the function" which effectively "goes back" to the function body): 有两个主要的例外(撇开显而易见的“定义函数,调用函数”,它有效地“返回”函数体):

1: Hoisting. 1:吊装。 var statements are hoisted, so if you write var语句被提升,所以如果你写

alert(a);
var a = 123;

You get undefined , and not an error message. undefined ,而不是错误消息。 This is because it is hoisted to 这是因为它被提升到了

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

Similarly, function definitions are hoisted too. 同样,函数定义也被提升。 If you write: 如果你写:

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

It will work, because the function is hoisted. 它会起作用,因为函数是悬挂的。 However, this does NOT work if you wrote 但是,如果你写的话,这不起作用

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

Because that's an assignment of an anonymous function, not a function definition. 因为这是匿名函数的赋值,而不是函数定义。

2: Asynchronous functions. 2:异步功能。

A common mistake among beginners is to write this: 初学者的一个常见错误就是这样写:

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);

They expect the alert to say Done! 他们希望警报说完了Done! , but instead they get an inexplicable error about it not being defined. ,但他们得到一个莫名其妙的错误,没有被定义。 This is because the myvar = "Done!" 这是因为myvar = "Done!" hasn't been run yet, despite appearing earlier in the script. 尽管早在剧本中出现,但尚未运行。


See also this anecdote from Computer Stupidities : 另见Computer Stupidities的这个轶事:

An introductory programming student once asked me to look at his program and figure out why it was always churning out zeroes as the result of a simple computation. 一位入门编程的学生曾经让我看看他的程序,并弄清楚为什么它总是因为简单的计算而产生零。 I looked at the program, and it was pretty obvious: 我查看了该程序,这很明显:

 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; 
  • Me: "Well, your program can't print correct results before they're computed." 我:“好吧,你的程序在计算之前无法打印出正确的结果。”
  • Him: "Huh? It's logical what the right solution is, and the computer should reorder the instructions the right way." 他:“嗯?正确的解决方案是合乎逻辑的,计算机应该以正确的方式对指令进行重新排序。”

I think they tried to put you on your wrong foot. 我想他们试图让你走错路。 Javascript is sequensial. Javascript是有序的。 Otherwise functions where you calculate values won't work out. 否则计算值的函数将无效。 What can be true is that console.log activates an Async task which means it can be executed in a different order. 可能是真的是console.log激活Async task ,这意味着它可以以不同的顺序执行。 Like an Ajax call, a Webworker , a timeout or an interval . Ajax调用, Webworkertimeoutinterval

If you do the following it will result B than A, this is not a sequensial code because in code. 如果你执行以下操作,它将导致B比A,这不是一个顺序代码,因为在代码中。 A comes for B but B is executed first. A代表B,但B首先执行。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM