2

これが重複している場合は、これが何の重複か教えてください。複数の関数で再利用される js クロージャーを作成するにはどうすればよいですか? 私はそれを理解できないようです。何かが欠けている可能性がありますが、内部関数を再実装し続ける (クロージャーを作成する) か、関数を外部に配置する必要があります (しかし、それはもはやクロージャーではありません)。両方を同時に行うにはどうすればよいですか?

例: したがって、js クロージャーは次のように作成されます。

function a()
{
    var x = "99";
    var b = function()
    {
       //x=99
    }
}

function z()
{
    var x = "99";
    var b = function()
    {
       //x=99
    }
}

ただし、これは閉鎖ではありません。

function bTemplate()
{
   //when coming from call of b() in m, x will not be the x from function m!
}
function m()
{
    var x = "99";
    var b = bTemplate;
    b(); //x is not the x from function m
}
function n()
{
    var x = "98";
    var b = bTemplate;
    b(); //x is not the x from function m
}

私の質問は次のとおりです: * (繰り返しを避けるために) 外部から関数を定義する方法と、同時にクロージャーを作成して、引数を渡す必要がないようにする方法は? たぶんそれは本当に明白なことですが、何らかの理由でそれを理解することはできません. *

たとえば、m と n がわずかに異なるラッパー関数である場合、両方の内部関数として bTemplate を実装せずに両方の状態を取得するにはどうすればよいでしょうか?

ありがとう!

4

8 に答える 8

2

考えられるアプローチの 1 つを次に示します。

function make_b(x) {
    var b = function() {
        //x come from argument to make_b
    };
    return b;
}

function a() {
    var x = "99";
    var b = make_b(x);
}

function z() {
    var x = "99";
    var b = make_b(x);
}

これにより、関数bを 1 か所だけで定義でき、クロージャーを使用しaて渡されることなくzの値にアクセスできます。これはあなたの要件に合っていると思いますが、単にに渡したくない理由はまだ少し不明です。xbxb

于 2013-04-15T21:49:10.620 に答える
1

次のようにして問題を解決できますか:

function cl() {
    var x = 99;

    var funcs = {};
    funcs.a = function() {
        return x;
    }

    funcs.b = function() {
        return 2*x;
    }
    return funcs;
}

theFuncs = cl();

theFuncs.a();
theFuncs.b();
于 2013-04-15T21:40:11.080 に答える
1

レキシカルスコープのポイントを完全に見逃しています。

あなたの例では、関数 a と b は同じスコープに属しているため、それぞれに完全に見えない内部スコープチェーンが必要です。あなたがやろうとしている方法は、JavaScript インタープリターの動作に違反しているため、独自の DSL などを発明しない限り不可能です。

2 番目の例を使用する必要があります。

于 2013-04-15T21:44:46.133 に答える
1

this関数に暗黙的に渡される引数を利用できます。ただし、パラメーターとして明示的に宣言されていなくても、まだ何かを「渡しています」。

function bTemplate()
{
   // here use this.x
}
function m()
{
    this.x = "99";
    bTemplate.call(this);
}
function n()
{
    this.x = "98";
    bTemplate.call(this);
}
于 2013-04-16T19:59:46.053 に答える
0

できません。これがレキシカル スコープの要点です。変数の使用は、レキシカルに囲まれたスコープ、つまりソース コード内で変数を物理的に囲むスコープで定義された変数を参照します。したがって、ソース コードを確認するだけで、参照されている変数を特定できます。

したがってx、関数で変数を使用する場合は、パラメーターまたはローカル変数のいずれかであるか、字句的に囲まれたスコープで定義する必要があります。

呼び出しスコープ内の変数を参照できるようにする場合、それは動的スコープと呼ばれます。動的スコープは興味深いものですが、直感的ではありません。歴史的に、動的スコープを使用する言語がいくつかありました。現在、一般的に使用されている言語で動的スコープを使用するものはありません (Perl で動的スコープを実行するようにすることはできますが、デフォルトではまだレキシカル スコープのままです)。

于 2013-04-16T08:16:24.590 に答える
-1

2 つの可能な解決策。

1。物議を醸す を使用しeval()ます。

function changeX() {
  x += 40;
  console.log(x);
}

function a() {
  var x = 7;
  eval(changeX.toString());
  changeX();
}

二。クロージャーで恋愛を落としましょう。好きなフレーバーで「通常の」オブジェクトを使用してください。

function Closure() {
  this.changeX = function() {
    this.x += 40;
    console.log(this.x);
  }
}

function a() {
  Closure.apply(this);
  this.x = 1;
  this.changeX();
}

function b() {
  Closure.apply(this);
  this.x = 2;
  this.changeX();
}

function c() {
  this.x = 3;
  this.changeX();
}
c.prototype = new Closure();

... または、オブジェクトを構築することを好みます。

「通常の」オブジェクトとクロージャーの唯一の違いは、少なくとも質問に関係する場合this.、変数の前に存在することです。

個人的には、アプローチ 2 をお勧めします。オブジェクトを作成し、入力することに慣れてthis.くださいthat.eval()仕事を成し遂げますが、それは物議をかもし、不必要です。

于 2013-04-15T22:01:57.297 に答える