[TIL]JS-再回帰深化



Today I Learned


Memoization

  • JSでは、再帰関数を呼び出すたびにスタックに蓄積されるため、処理時間が長くなる可能性があり、一度に多くの呼び出しを返さずに蓄積するとスタックがオーバーフローする可能性があります.
  • Memoizationを使用する利点は、呼び出し結果値を格納し、不要な繰り返し呼び出しを低減できることである.
  • 例:フィボナッチ

    function fibonacci(num, memo) {
      memo = memo || {};
      if (num < 2) return num;
      if (num in memo) return memo[num];
      memo[num] = fibonacci(num - 2, memo) + fibonacci(num - 1, memo);
      return memo[num];
    };

    Tail Call Optimization

    // What is tail call?
    function foo(x) {
      return bar(x); // tail call
    }
    
    function bar(x) {
      return x-1;
    }
    
    function baz(x) {
      return baz(x-1); // recursive tail call
    }
  • TCOをサポートするエンジンでは、tail callが終了すると含まれる関数も終了し、新しいスタックフレームは作成されず、既存のスタックフレームが使用されることに気づきます.したがって、TCOがない場合よりも高速で、メモリも少なくなります.(すべてのブラウザでサポートされているわけではありませんが、現在サポートされているのはSafariのみです.)
  • TCOの再帰関数を用いた場合,基本状況に達した場合には全結果値が得られる.
  • 例:ファクトリ

    // Naive Facotiral
    function factorial(num) {
      if (num <= 1) return 1;
      return num * factorial(num-1);
    }
    
    // TCO Factorial
    function factorial(num, acc) {
      // acc에 결과값을 누적시켜 전달
      acc = acc || 1;
      if (num <= 1) return acc;
      return factorial(num-1, num*acc);
    }

    JSON.stringify()

  • JSON(JavaScript Object Notation)は、JSから派生した軽量レベルのデータ交換フォーマットで、JSのようなフォーマットを持つが、言語とは独立している.主に非同期ブラウザ/サーバ通信に使用されます.
  • JSには、値またはオブジェクトをJSON文字列(JSON.stringify())に変換する方法と、JSON文字列を値またはオブジェクト(JSON.parse())に変換する方法が組み込まれている.
  • JSONはkey:value形式でフォーマットされ、通常""が使用されます.
  • はすべてのデータ型がJSONでグループ化できるわけではありません.functionおよびundefinedは穿孔できない.
  • JSON.再帰関数でstringify()を実現する

    function stringifyJSON(obj) {
      // 1. Number
      if (typeof obj === "number") {
        return `${obj}`;
      }
      // 2. Boolean
      if (typeof obj === "boolean") {
        return `${obj}`;
      }
      // 3. String
      if (typeof obj === "string") {
        return `"${obj}"`;
      }
      // 4. Null
      if (obj === null) {
        return `${obj}`;
      }
      // 5. Array
      if (Array.isArray(obj)) {
        // if the array is empty
        if (obj.length === 0) return `[]`;
    
        const result = [];
        for (let el of obj) {
          result.push(stringifyJSON(el));
        }
        return `[${result.join(",")}]`;
      }
      // 6. Object
      if (typeof obj === "object") {
        // if the object is empty
        if (Object.keys(obj).length === 0) return `{}`;
    
        const result = [];
        for (let key in obj) {
          // if the type of value is function && not undefined
          if (typeof obj[key] !== "function" && obj[key] !== undefined) {
            const str = `"${key}":${stringifyJSON(obj[key])}`;
            result.push(str);
          }
        }
        return `{${result.join(",")}}`;
      } 
    };