2

関数にローカル テーブル変数があり、同じ名前の変数を持つはずの子関数がありますが、親の変数にはアクセスできます。これは明白で簡単なはずですが、残念ながら、どこかに同じ名前のローカル変数を定義すると、JavaScript では親の変数にアクセスできません。

var p = {alpha : 'beta'};

console.debug (p);
// [08:16:21.896] ({alpha:"beta"})
// Okay.

(function() {
    console.debug (p);
    // [08:16:21.896] ({alpha:"beta"})
    // Right! JavaScript, you're so awesome!
})();

// One moment though, I think I still need the parent's table...
(function() {
    var p = { 'p': p };
    console.debug (p);
    // [08:16:21.896] ({p:(void 0)})
    // Wait, what?
})();

// Okay, maybe giving it the same name in the same statement confuses you?
(function() {
    var parent_p = p;
    var p = {};
    console.debug (parent_p);
    // [08:16:21.897] undefined
})();
// Give me back my variable! http://v.gd/jsWhyDoYouDoThis

何が起こっているのですか?これを回避する方法はありますか?

4

3 に答える 3

2

いいえ、標準の ECMAScript でこれを行う方法はありません。

ブロック内の任意のvar宣言は、そのブロック内の名前付き変数のすべての使用がローカル変数を参照するという JS パーサーへの指示です。JS では、この目的のブロックは周囲の関数、または関数定義内にない場合はグローバルです(*)。

したがって、最後の例では、まだ何も割り当てていないのでparent_p、ローカル変数の値を割り当てています。pundefined

変数名を絶対に再利用する必要がある場合は、中間スコープを使用して参照を保存する必要があります。

(function() {
    var parent_p = p;
    (function() {
        var p = {};
        console.debug (parent_p);
    })();
})();

ECMAScript の将来のリビジョンでは、Mozilla JS 拡張機能が採用される可能性があります。この拡張let機能では、関数よりも小さな定義ブロックが導入されます。これにより、これをより簡単に綴ることができます。

(function() {
    var parent_p = p;
    let (p = {}) {
        console.debug (parent_p);
    }
})();

もう 1 つの一般的な方法は、変数を引数として渡すことです。

(function(parent_p) {
    var p = {};
    console.debug (parent_p);
})(p);

(*: グローバル オブジェクトを使用してグローバル スコープから変数を読み取ることができます。つまりwindow.p、非グローバル スコープを囲むローカル変数を取得することはできません。)

于 2013-07-03T00:56:57.820 に答える
1

acdcjunior の正解に対する代替ビューとして:

関数スコープ (ブロックスコープなし) と巻き上げのため、次のようになります。

(function() {
    var parent_p = p;
    var p = {};
    console.debug (parent_p);
    // [08:16:21.897] undefined
})();

になります:

(function() {
    var parent_p, p;  //both undefined
    parent_p = p;     //undefined
    p = {};
    console.debug (parent_p);
    // [08:16:21.897] undefined
})();

したがって、これを解決するには、変数を含むオブジェクトのプロパティとして変数にアクセスします。この場合、直接プロパティの 1 つとしてwindow保持される「ホスト」/「ルート」オブジェクトです。p

(function() {
    var parent_p = window.p,
               p = {};
    console.debug (parent_p);
    // [08:16:21.897] ({alpha:"beta"})
})();
于 2013-07-03T00:58:04.293 に答える