2016-02-21 5 views
43

ES6クラスではJavaScriptの既存のプロトタイプベースの継承[1]上だけ構文砂糖ですので、それは(IMO)それが定義だホイストするために理にかなって:なぜES6クラスは持ち上げられないのですか?

var foo = new Foo(1, 2); //this works 

function Foo(x, y) { 
    this.x = x; 
    this.y = y; 
} 

が、以下では動作しません。

var foo = new Foo(1, 2); //ReferenceError 

class Foo { 
    constructor(x, y) { 
     this.x = x; 
     this.y = y; 
    } 
} 

なぜES6クラスが吊り上げられないのですか?

+3

ES6クラス*は構文的な砂糖ではありませんが、主に構文的な砂糖です。 –

+2

ホイストは、誤解と混乱のほとんど無限の原因となっています。 ES6に追加されたすべての新しい宣言構造体( 'let'、' const'、 'class')は、吊り上げられていません(まあ、半分吊り*です)。 Eichまたはそれに類するものからの引用を除いて、あなたは効果的な推測ではない答えを得るつもりはない。 –

+0

@mmm:MDNはコミュニティによって編集されていますが、間違っていることもあります。しばしば、他のサイトほど頻繁にはないが、時にはそうではない。それらがどのように吊り上げられていても持ち上げられていないかについては、[この回答](http://stackoverflow.com/a/31222689/157247)を参照してください。 –

答えて

41

なぜES6クラスが吊り上げられないのですか?

は、実際に彼らは掲揚を(結合変数が全体のスコープで利用可能である)だけlet and const are等である - 彼らは唯一の初期化されていません。

それは、その定義の前にクラスを使用することをお勧めことはない第

その定義をホイストするために理にかなって。例に

var foo = new Bar(); // this appears to work 
console.log(foo.x) // but doesn't 

function Bar(x) { 
    this.x = x || Bar.defaultX; 
} 
Bar.defaultX = 0; 

を考えてみましょう、あなたが期待するようなエラーがスローされます

var foo = new Bar(); // ReferenceError 
console.log(foo.x); 

class Bar { 
    constructor (x = Bar.defaultX) { 
     this.x = x; 
    } 
} 
Bar.defaultX = 0; 

と比較します。これは、静的なプロパティ、プロトタイプのミックスイン、デコレータ、およびすべての問題です。また、調整されていないプロトタイプでクラスを使用したときにES5で完全に破られたサブクラス化では非常に重要ですが、extend edクラスがまだ初期化されていない場合はエラーをスローします。 JavaScriptで

+0

最初の例を明確にするために、 'console.log(foo.x)'は実行時エラーではなく '0'ではなく' undefined'を生成するという問題があります。 –

3

すべての宣言(VAR、聞かせて、constの、機能、機能*、クラス)が掲揚されているが、それは同じスコープに宣言する必要があります。あなたは

は、それでは、それが何であるかを理解しましょう「ES6クラスではJavaScriptの既存のプロトタイプベースの継承の上にちょうど構文砂糖です」言われたよう

ここでは、実際には「特殊関数」であるクラスを宣言しました。関数Foo()とクラスFooの両方がグローバルスコープにあるとしましょう。

class Foo { 
    constructor(x, y) { 
     this.x = x; 
     this.y = y; 
    } 
} 

以下は、Fooクラスのコンパイル済みコードです。

内部的に、クラスはラッパー関数(iife)内で同じ名前の関数に変換され、そのラッパー関数は関数を返します。

関数の(クラス)スコープが変更されているためです。現実には存在しないグローバルスコープで機能のオブジェクトを作成しようとしています。

コンパイルが完了すると、変数Fooで関数を取得します。後であなたはvarの関数を持っていますので、そのオブジェクトを作成することができます。

+0

同様の効果がありますが、これは起こりません。クラスを評価するためのIIFEは作成されません。私が間違っていない場合は、このiifeの構文(function(){}())をhttps://www.ecma-international.org/ecma-262/8.0/#sec-runtime-semantics-classdefinitionevaluation –

+0

にしてください。クラスをコンパイルすると、このコードが生成されます。これはvarに割り当てられているため、グローバルには呼び出されません。代わりに自己が呼び出され、Fooに値が返されます。 –

+0

あなたがバーベルのようなものを使っているなら、そうです。しかし、クラスをネイティブにサポートしている環境では、それを実行できません。 –

関連する問題