0

これは、john resig の Learning Advanced Javascript アプリにあるものを改造したものです。

var math = {
    fact: function fact(n){
        return n > 0 ? n * fact(n-1): 1;
    },
    fact1: function (n) {
        return n > 0? n * math.fact1(n-1) : 1;
    }
};

console.log(math.fact(5));  // 120
console.log(math.fact1(5)); // 120

var o = {
    x: math.fact,
    y: math.fact1
};

math = {};

console.log(o.x === undefined); // false
console.log(o.y === undefined); // false
console.log(o.x(5));            // 120
console.log(o.y(5));            // Uncaught TypeError: math.fact1 is not a function

エラーがo.x(5)スローされるはずですが、実行されます。なんで?

4

3 に答える 3

5

オブジェクト リテラル式が評価されると、各コロンの右側にある式が評価され、指定されたプロパティに割り当てられます。

したがって、これが実行されると:

var o = {
    x: math.fact,
    y: math.fact1
};

式が評価され、結果はその時点で参照してmath.factいる関数です。math.fact

についても同様ですmath.fact1

したがって、math変数をmath = {}. o.x引き続きその機能を参照します。oオブジェクトはmath変数 を認識していません。


o.y(5)エラーをスローする 理由は、クロージャーに関係しています。

o.yこの機能を指します:

function (n) {
     return n > 0? n * math.fact1(n-1) : 1;
}

math 変数を使用していることがわかります。変数を再割り当てしてもmath、この関数は引き続き変数自体を参照します。

を呼び出すo.y(5)と関数が実行されますが、 を呼び出そうとすると、というプロパティがなくなっmath.fact(n-1)たため失敗します。mathfact


o.x持っている問題はありませんo.y。これは名前付き関数であるため、再割り当て後も引き続き自分自身を呼び出すことができmathます。

于 2014-12-10T11:27:56.450 に答える
3

でエラーが発生する理由がわかりませんo.x

最初に を定義するmath = { ... }と、2 つの関数ができます。

最初の関数は、その名前とオブジェクト プロパティの両方によって参照されます。factmath.fact

2 番目の関数は匿名であり、によってのみ参照されます。math.fact1

次に、関数を に「コピー」しますo。この時点で、最初の関数はすべてのfactmath.factおよびによってo.x参照され、2 番目の関数は および によって参照されmath.fact1ますo.y

math次に、オブジェクトを新しい空のオブジェクトに置き換えて破棄します。この時点で、最初の関数は と によって参照されfacto.x2 番目の関数は のみによって参照されo.yます。

実際に関数を呼び出します。o.xへの再帰呼び出しが含まれておりfact、その関数として非常に明確に定義されています。ただし、破棄o.yした への再帰呼び出しが含まれているmath.fact1ため、エラーが発生します。

これは何の関係もありません...まあ、興味深いものです。まだ存在するものに名前を付ける関数は引き続き機能しますが、存在しなくなったものに名前を付ける関数は失敗します。

つまり...当たり前...

于 2014-12-10T11:32:36.540 に答える
1

o.x関数 (オブジェクト) への参照です。この参照により、数学オブジェクトがリセットされた後もファクト関数は存在し続けます (オブジェクトへの参照が存在しなくなった場合にのみ、オブジェクトはガベージ コレクションされます)。

于 2014-12-10T11:32:37.717 に答える