2

Javascript Koans を使って作業していると、次のコードに行き詰まります。

    it("should use lexical scoping to synthesise functions", function () {

function makeMysteryFunction(makerValue)
{
  var newFunction = function doMysteriousThing(param)
  {
    return makerValue + param;
  };
  return newFunction;
}

var mysteryFunction3 = makeMysteryFunction(3);
var mysteryFunction5 = makeMysteryFunction(5);

expect(mysteryFunction3(10) + mysteryFunction5(5)).toBe(FILL_ME_IN);
});

23 になり、それで問題ありません。私が困惑しているのは、「mysteryFunction3」変数に指定されたパラメーターが「param」としてdoMysteriousThing関数に渡される方法/理由です。

それぞれが1つのパラメーターを受け取る内部関数と外部関数がある場合、次のように指定されたパラメーターが指定された外部関数と等しい変数を定義するのは、単なる現実ですか?

    var mysteryFunction3 = makeMysterFunction(3);

次のように、パラメーターを外部関数の変数インスタンスに送信するようにします。

   mysteryFunction3(10)

そのパラメーター (10) が内部関数のパラメーターとして読み取られるようになりますか?

4

3 に答える 3

1

私も最初はこれを理解するのに苦労しました。これが、一撃一撃で明確に到達した方法です。これはスタックに関する私の最初の投稿であり、それについて長々とすみません。

文字列を返す非常に基本的な関数を見てみましょう:

function fun() {
       return 'Hi!';
    }

呼び出し括弧なしで上記の関数をログに記録すると、コンソールは関数への参照をログに記録するだけです。

console.log(fun); //logs ---> [Function: fun] 

もう一度ログに記録しますが、呼び出し括弧を使用すると、次のようになります。

console.log(fun()); //logs ---> Hi!

関数の呼び出しは、その戻り値と同じです。

console.log(fun() === 'Hi!'); //logs ---> true

その上で、関数を書き直して、文字列を返す別の関数を内部で宣言しましょう。外側の関数は、内側の関数の呼び出しを返します。

function funAgain() {
   function innerFun() {
     return 'Hello there!';
   }
   return innerFun();
}

したがって、funAgain のスコープ内 (innerFun() === 'Hello there!') は true と評価されるため、funAgain の呼び出しをコンソールに記録すると、次のようになります。

console.log(funAgain()); //logs ---> 'Hello there!'

しかし、外部関数の return ステートメントで innerFun の呼び出し括弧を省略したらどうなるでしょうか?

function funAgain() {
  function innerFun() {
    return 'Hello there!';
  }
  return innerFun;
}

console.log(funAgain()); //logs [Function: innerFun]

関数 ITSELF が返されます。実際にはすべての話ではありませんが、(funAgain() === innerFun) と考えることができます。明らかに、スコープの問題のため、実際にこの比較を実際に実行することはできません (innerFun は funAgain の呼び出しの外に存在することはできません)。 . しかし!ちょっとそんな風に考えてみましょう。つまり、funAgain の戻り値を変数に取り込むと、次のようになります。

var innerFunCaptured = funAgain();

console.log(innerFunCaptured); // logs [Function: innerFun]

ここでも概念的には (innerFunCaptured === innerFun) ...

変数が内部関数にバインドされたので、変数に括弧を追加してその内部関数を呼び出すことができます。

console.log(innerFunCaptured()); //logs ---> 'Hello there!'

上記の「全体の話」について話していたとき、私が省略したのは、内部関数の変数へのバインディングは外部関数の呼び出しの結果であるため、実際にはバインディングには innerFun 自体だけでなく、それが存在する環境も含まれるということです。外部関数の呼び出しを介して渡される潜在的な引数を含めて作成されました。これにより、次のことが可能になります...

相互作用するパラメーターを持つように、外側と内側の関数をもう一度書き直します。

function funOnceMore(greetingPartOne) {
  function innerFun(greetingPartTwo) {
    return greetingPartOne + ' ' + greetingPartTwo;
  }
  return innerFun;
}

funOnceMore を引数付きでログに記録するとどうなるでしょうか。

console.log(funOnceMore('Hello')) //logs ---> [Function: innerFun]

ここでも、innerFun 自体が返されます。しかし、渡した引数 greetingPartOne はどうなるでしょうか。まあ、問題なく渡されましたが、funOnceMore 内で innerFun が呼び出されなかったため、 greetingPartOne が意味のある方法で使用されることはありませんでした。innerFun を呼び出す方法を理解する必要があります。答え: 前のステップで行ったように、変数にバインドする必要があります。

var innerFunCapturedAgain = funOnceMore('Hello')

これで、innerFunCapturedAgain は、innerFun と、渡した引数 'Hello' を持つ funOnceMore の環境を保持します。

これで、innerFunCapturedAgain に括弧を付けて innerFun を呼び出すことができます。これらの括弧は、innerFun に渡す greetingPartTwo の引数をカプセル化します。

console.log(innerFunCapturedAgain('there!')) //logs ---> 'Hello there!'
于 2021-03-15T04:11:08.440 に答える
0

両方の答えは非常に役に立ちますが、これを自分で苦労して、最善の答えは、何が起こっているのかを見て、それに新しい光を当てるのに十分なだけ変更することだと思います:

makeMysteryFunctionmakerValueその引数 ( ) を、それが返す関数 ( ) に渡される引数に追加する関数を作成しますmysteryFunctionX

それで、これを理解するのに役立ったのは、数値を文字列に変換することです:

function makeGreeting(greeting)
{
  var newFunction = function greet(name)
  {
    return greeting + ' ' + name;
  };
  return newFunction;
}

var makeGreetingHi = makeGreeting('Hi');
var makeGreetingHello = makeGreeting('Hello');
//finally call functions
makeGreetingHi('Stranger');
//Hi Stranger
makeGreetingHello('Friend');
//Hello Friend

私がしたことは、関数の名前を変更し、数字を追加する代わりに文字列を連結することだけでした。公案を混乱させているのは関数名です。これは悪い習慣の良い例だと思います。演習の要点は、私が提供した例では、greet関数が にアクセスできるということgreetingです。残念ながら、それは命名法で失われました

于 2014-05-13T03:19:28.420 に答える