2016-12-06 16 views
2

JavaScriptを学んでいますが、理解できないことがたくさんあります。
は、次のJavaScriptコードのログは何をコンソールになります:1問のオンラインのJavaScriptクイズでは、次の質問が現れJavaScript:関数実行命令

const a = {}; 
const b =() => a.a =() => {}; 
const c = c => '' + c + a.a(b()); 
const d = console.log.bind(console); 
const e = (e =>() => d(c(e++)))(0); 

try{ 
    e(); 
}catch(a){ 
    e(); 
} 

これは、各変数(ここでは定数)の略かを理解するために私にいくつかの時間がかかりました。 ブロック内のe()のコードの解析を開始しました。したがって、eはクロージャを表します。つまり、関数dが引数c(0)で呼び出され、e1になります。私が理解したように、dは基本的にconsole.log関数を表しています(しかし、なぜ彼らはbindを使用しましたか?)

今のところ私は最初にc(0)が実行され、コンソールに結果が記録されることを知っていますか?関数cを見てみましょう。最初の引数を文字列に変換し、連結結果をa.a(b())に返します。さて、a.a(b())が最初に実行されるでしょう、そうですか?しかし、問題はa.aが関数ではないため、定義されていないため、エラーがスローされ、catchに行きます。

今、catchブロックではすべてが同じである必要があります。したがって、a.aはまだ関数ではなく、参照エラーがスローされるはずです。しかし、それはエラーがスローされていないことを見たとき私は驚いたが、コンソールは実際に1undefinedを記録する。どうして?どうやって?

私は少し考えた後、おそらくa.a(b())b()と呼び出すと、最初に実行されることに気づきました。私の想定に従えば、オブジェクトaのオブジェクトaのプロパティに何もしない関数への参照bの参照を右に?しかし、a.aは関数であり、tryブロックで実行され、0undefinedがログに記録されます。

しかし、これらの2つの仮定は正しいものではありません。ここでの主な質問は最初に実行されるものです。 someObject.propertyWhichIsNotAFunction(somethingWhichMakesItAFunction)とすると、どうなりますか?最初に実行されるのは何ですか? tryブロック1つがまず実行され、catch他のものであるようです。それは本当に私にとって意味をなさない。説明は?

答えて

1

これはWhy is the value of foo.x undefined in foo.x = foo = {n: 2}?の原因に非常に似ていますが、実行時にTypeErrorがスローされたときに依存しているため、やや厄介です。

は、基本的に何が起こるかです:

  1. a.a

    は、後のステップ3でと呼ばれるものを機能を調べるために評価されます。
  2. b()が評価されます。これは関数の引数であり、戻り値 の値はa.aと評価された値の実際の値になります。
  3. ステップ1で評価されたa.aは、戻り値b()を引数として実行されます。

仕様の関連部分はここにある:

  1. REFは、結果とします:関数が呼び出されたときに起こる最初のものであることをhttps://www.ecma-international.org/ecma-262/7.0/index.html#sec-function-calls

    お知らせMemberExpressionを評価します。

  2. funcは? GetValue(ref)。 a.aが評価され、それが指す関数をfunc呼び出されることを意味

a.a最初の頃はそうfuncundefinedで、例外TypeErrorがb()を呼び出し、a.aに新しい値を代入しますが、後のないArgumentListEvaluation(arguments)、あるhttps://www.ecma-international.org/ecma-262/7.0/index.html#sec-evaluatedirectcallのステップ2、でスローされます、undefinedに評価しますfuncの値。

+0

これは、 'a.a'が関数でない場合、引数を評価する際に何が起こっても、参照エラーをスローする必要があることを意味します(評価自体がエラーをスローする場合を除く)。まあ、それはかなり変だ。私はJavaScriptが 'f1()'や 'f2()'のような不必要な計算を避けるように設計されていると考えました。私たちが呼ぶことができないことを確かに知っている関数参照の引数を評価するロジックは何ですか? –

+0

@ manga171引数に 'b()'のような副作用があります。 specは最適化以上の正しさに焦点を当てており、 'isReady()&& go()'は 'go() 'を呼び出さないことが保証されているなど、' f1()&& f2() 'if' isReady() 'false' false'を返すと、関数を呼び出す前に関数の引数を評価しないことによるメリットはありません。反対の質問はもっと面白いです:引数を評価する前に関数参照を評価するロジックは何ですか? – Paulpro

+0

@ manga171その答えはおそらく、仕様が完璧ではなく、既存のコードに影響を与える変更を行うことは大したことです。 'let argListはどうするの? ArgumentListEvaluation(Arguments).'が常に発生するので、任意の条件から取り除き、関数が評価されたときに最初に実行することは可能ですが、問題のコードの動作は変更されます例外を投げることはありません。私は '0undefined'を出力すると思います。 – Paulpro

関連する問題