私はすべての微妙なことを理解すると主張しませんが、これについての重要なことは、附属書Bの§B.3.3.1のほとんど奇妙な歪曲です。 f1
ブロック(以下従ってlet
)の字句環境へf
の第2のコピー特定のコードは、これを効果的にしていることを
:
var p =() => console.log(f);
{
let f1 = function f(){};; // Note hoisting
p(); // undefined
console.log(f1); // function f(){}
f1 = 1;
p(); // undefined
console.log(f1); // 1
var f = f1; // !!!
p(); // 1
console.log(f1); // 1
f1 = 2;
p(); // 1
console.log(f1); // 2
}
そしてもちろん、var
巻上げのおかげで、両方p
var f = undefined;
var p = undefined;
p =() => console.log(f);
{
let f1 = function f(){};; // Note hoisting
p(); // undefined
console.log(f1); // function f(){}
f1 = 1;
p(); // undefined
console.log(f1); // 1
f = f1; // !!!
p(); // 1
console.log(f1); // 1
f1 = 2;
p(); // 1
console.log(f1); // 2
}
キービットから:とf
を効果的に初期値undefined
とコードスニペットの先頭に宣言されていますB.3.3.1は、内側の値f
(上記ではf1
と呼んでいます)を外側に転送します(Fは、文字列"f"
、宣言されている関数の名前です)。
F FunctionDeclarationの
が評価さ
3、14.1.21に設けFunctionDeclarationの評価アルゴリズムの代わりに、次の手順を実行し
。 fenvを実行コンテキストのVariableEnvironmentとします。
b。 fenvRecはfenvのEnvironmentRecordになります。
c。 benvを実行コンテキストのLexicalEnvironmentとします。
d。 benvRecをbenv's EnvironmentRecordに差し上げましょう。
e。 がfobjになるようにしましょう! benvRec.GetBindingValue(F、false)。
f。実行! fenvRec.SetMutableBinding(F,fobj、false)。
g。 NormalCompletion(空)を返します。
変数環境が関数全体であるが、字句環境は(ブロック)は、より拘束されることを想起されたいです。
関数宣言を正規化しようとすると、{無効|不特定多数)、TC39は非常にです。過去の実装固有の動作に依存していた可能性のある既存のコードを破損しないように、動作を標準化しようとする危険なパスです(相互排他的です。 TC39はバランスを取ろうとしている)。
特にホスティングとの関係では?この回答は非常によく説明しています:http://stackoverflow.com/questions/25111087/why-is-a-function-declaration-within-a-condition-block-hoisted-to-function-scope – CodingIntrigue
@CodingIntrigue:いいえ、これは、ES2015の附属書BとTC39の成果物であり、既存のコードと歴史的に一貫性のない実装の真っ逆さましい海域を操るために最善を尽くしたものです。 :-) –
@ T.J.Crowderもっと詳しく説明してください。 'function f(){}'は通常通常の関数ブロックの中に持ち込まれ、最初の 'undefined'は関数f宣言を出力するはずですが、ブロック内で定義されているのはどうですか? – kstratis