5

At a job interview, I was perplexed to hear "javascript can evaluate statements out of order." 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. 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, i.e. no side effects, but side effects must always occur in sequence, correct? And of course IO is one big side effect.

To what extent can spec-compliant Javascript evaluate out of order? Or was this a case of miscommunication?

4

4 に答える 4

8

JavaScriptはシングルスレッドです(Webワーカーは別として)。限目。ECMA-262 Language Specification Edition 5.1は、アウトオブオーダー実行については何も述べていません。簡単な例では、これら2つのステートメントは同じ順序で実行されることが保証されています。

さらに、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エンジンがこれらのイベントを並べ替える可能性があります。結局のところ、これらの呼び出しをほぼ同じ時点で実行するようにスケジュールします。

于 2013-01-31T20:13:55.810 に答える
2

明らかに誤解。

男はおそらくJavaScriptの巻き上げについて言及していました。詳細については、こちらをご覧ください:http ://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

さらに、ここで言語の詳細を学ぶことができます:http: //bonsaiden.github.com/JavaScript-Garden/

于 2013-01-31T20:15:04.980 に答える
1

ほとんどの場合、そうです。2つの主要な例外を除いて(明白な「関数を定義し、関数を呼び出す」は別として、関数本体に効果的に「戻る」):

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!"、スクリプトの前半に表示されているにもかかわらず、がまだ実行されていないためです。


ComputerStupiditiesからのこの逸話も参照してください。

プログラミング入門の学生が、自分のプログラムを見て、単純な計算の結果として常にゼロを解き放つ理由を理解するように私に頼んだことがあります。私はプログラムを見ました、そしてそれはかなり明白でした:

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;
  • 私:「まあ、あなたのプログラムは計算される前に正しい結果を印刷することはできません。」
  • 彼:「え?それは正しい解決策が何であるかは論理的であり、コンピューターは正しい方法で命令を並べ替える必要があります。」
于 2013-01-31T20:18:56.790 に答える
0

彼らはあなたをあなたの間違った足に乗せようとしたと思います。Javascriptはシーケンシャルです。そうしないと、値を計算する関数が機能しません。真実である可能性があるのは、それが異なる順序で実行できることを意味するをconsole.logアクティブ化することです。呼び出しのAsync taskように、、、または。AjaxWebworkertimeoutinterval

次のようにすると、AよりもBになります。これは、コード内にあるため、シーケンシャルコードではありません。AはBになりますが、Bが最初に実行されます。

setTimeout(function(){
    console.log("A")
}, 5);
console.log("B");
于 2013-01-31T20:13:09.397 に答える