クローズド&IIFEコンセプト(Feat.モノトーンモード)

22990 ワード

♪ためらう
NodeJS言語を使って1~2年になるが、closureやIIFEの概念や応用方法については、混同されることもある.混同するたびに資料を調べますが、私の頭はとても揮発しやすいもののようで、振り向くと忘れてしまいました...
今回はclosureとIIFEを自分で整理して明確にしたコンセプトを後でもっと分かりやすくします!それを再理解させる形に加工したいです.
いずれにしてもclosure,IIFEの概念を理解する上でSingletonモードが最適な例であると考えられるので,上記3つの概念をまとめる.
レプリカ
Closerとは?
まず,Closerは関数内部の関数そのものを表す.
また、Closerの核心概念はScopeである.
私の知っている限りでは、すべてのプログラミング言語には最終的にscopeの概念があります.
JSも同様に,特定の変数に直接アクセスするためには,scopeで呼び出された変数ではなく,最終的に呼び出された位置が内部にあるか,あるいは同じ位置にある必要がある.
では、関数の状況はどうでしょうか.
他の場所から関数を呼び出すたびに呼び出される場所に基づいて内部環境を構成しますか?いいえ.
関数は、内部環境と役割ドメインからなる場所を宣言します.これをLexicalScoptingと呼びます.
また,JSが述べたように,各種の関数型プログラミング言語では,関数はいずれも1次オブジェクトである.このプログラミング言語では,関数の結果で関数を返すことができる.この場合、外部関数のライフサイクルは終了しますが、返される内部関数は引き続き使用できます.この場合、簡単に言えば、関数宣言位置に設定された環境のLexicalScoping概念は、外部関数のライフサイクルが終了することにより内部変数が消失し、環境の維持不可能な概念が相殺され、モジュールの特徴が生じる.
この特性により、モジュールを囲む外部関数が終了した後も、モジュールは環境を記憶し、外部関数のscope、contextにアクセスすることができる.
このセクションでは、次の例で説明します.

// 1. 변수 반환
function normalFunc(param) {
    let num = 0;
  
    return num += param;
}

// 2. 내부 함수(클로저) 반환
function outterFunc() {
    let num = 0;

    return function closureFunc(param) {
        return num += param;
    }
}

//   console.log(num); 			// scope 개념에 의해 당.연.히 불가능
console.log(normalFunc(5));  	// 5
console.log(normalFunc(10)); 	// 10

let closureFunc = outterFunc();    // 외부 함수 호출을 통해 클로저인 "closureFunc" 함수 반환
console.log(closureFunc(5)); 	    // 5
console.log(closureFunc(10));       // 15
ここでは,一般関数とモジュールの最大の違い,およびモジュールを使用する理由を見ることができる.
すなわち,モジュールを有する外部関数が終了しても,モジュールの外部コンテキストが記憶される.
一般的な関数の場合、関数を呼び出すたびに新しい関数のcontextに値を加算し続けると、モジュールでは、外部関数を呼び出して返されるモジュール(追加の外部関数呼び出しを必要としない)によって既存の外部関数のcontextが保持され、値が加算されるため、このことが発生します.
さらに、scopeコンセプトは、外部がnum変数に直接アクセスできないようにし、特定の関数のみでアクセスおよび操作できる制限的なインタフェースを提供する.(カプセル、隠匿化/プライベート、パブリックコンセプト)
エンクロージャのメリット
1.変更・追加したデータを記憶できる
前述したように、モジュールは、外部関数が終了してもcontextを保存して同じ外部変数にアクセスすることができる.したがって、closureアクセスにより、初期化のたびに外部変数の値にアクセスおよび操作する必要はありません.
2.隠匿、カプセル化
エンクロージャを使用してデータにアクセスすると、さまざまな制約が適用されるか、データを直接変更できないため、データが一定の形式で安全に動作することができます.
3.モジュール化が得意
エンクロージャは独立した値を持つことができるため、データとメソッドを組み合わせてモジュールとして使用する利点があります.
これらの3つの利点は,モジュールが外部Contextを記憶できるためであることが分かる.
IIFE(Immediately Invoked Function Expression)
IIFEとは?
IIFEは、宣言および定義と同時に実行される関数式を表す即時実行関数である.
IIFEは一般に匿名関数(Annonymous Function)で構成されている.これはIIFEで実現される関数に対して単独で呼び出すことができないためである.言い換えれば、IIFEが宣言した時点を除いて、この関数をどこでも呼び出すことは絶対にできない.
簡単な例を見てみましょう.

// 익명함수
const annonyFunc = function() {
    console.log("I'm Annonymous Function");
}

// IIFE
const iifeFunc = (function() {
    console.log("I'm IIFE Function");
})();						// "I'm IIFE Function"

annonyFunc();				// "I'm Annonymous Function"
// iifeFunc();				// 에러 발생 - TypeError: iifeFunc is not a function

console.log(annonyFunc);	// [Function: annonyFunc]
console.log(iifeFunc);		// undefined
このようにIIFEは宣言された場所ですぐに実行され、通常の関数は関数自体を指定すると[Function:関数名]を返し、IIFEを特定の変数に割り当てると戻り値を指定します.
なぜIIFEを使うのか
上記のIIFE定義を調べ,二つの事実を理解した.
第一に、IIFEは他の場所から呼び出すことができない.つまりIIFEは使い捨て
第二に、IIFE内部へのアクセスは、戻り値のみで行うことができる.
したがって,IIFEを用いた理由は以下のようにまとめることができる.
1.一度だけ(ex)初期化関数を実行する必要がある場合
2.隠匿、カプセル化
モノトーン(Singleton)
モノトーンとは?
モノクロはデザインモードです.簡単に設計モードといえば,プログラミングでよく遭遇する問題を解決する方法やマイルストーンと言える.
名前の通り、単一の色調は、特定のクラスに1つのインスタンスのみを作成するために使用される設計モードを意味します.
オブジェクト生成の繰返し性が高すぎてメモリの問題が発生した場合、一度だけ実行しなければならない機能を実行するモジュールを使用すると、モノトーンモードが適切です.
モノトーンWith Close/IFE
ここでは,closureで実現したモノトーンモードとclosureとIIFEで実現したモードを分けてみる.

// 1. With Only Closure
let singleton = function() {
    let instance;

    let length = 100;

    function init() {
        return {
            length: length,
            getLength: function() {
                console.log(length);
            },
          	setLength: function(a) {
              length = a;
            }
        };
    }
    
    return {
        getInstance: function() {
            if (!instance) {
                instance = init();
            }

            return instance;
        }
    }
}

// With Closure & IIFE
let singletonIIFE = (function() {
    let instance;

    let length = 100;

    function init() {
        return {
            length: length,
            getLength: function() {
                console.log(length);
            },
          	setLength: function(a) {
              length = a;
            }
        };
    }
    
    return {
        getInstance: function() {
            if (!instance) {
                instance = init();
            }

            return instance;
        }
    }
})();

const instance1 = singleton().getInstance();
const instance2 = singleton().getInstance();

console.log(instance1 == instance2);				// false

instance1.length += 100;
console.log(instance1.length);						// 200
console.log(instance2.length);						// 100
instance1.getLength();								// 100
instance2.getLength();								// 100
instance1.setLength(50);
instance1.getLength();								// 50
instance2.getLength();								// 100

const instance3 = singletonIIFE.getInstance();
const instance4 = singletonIIFE.getInstance();

console.log(instance3 == instance4);				// true

instance3.length += 100;
console.log(instance3.length);						// 200
console.log(instance4.length);						// 200
instance3.getLength();								// 100
instance4.getLength();								// 100
instance3.setLength(50);
instance3.getLength();								// 50
instance4.getLength();								// 50
分析の結果、以下の結論が得られた.
1.IIFEを使用しないとモノトーンオブジェクトと判断できない
初めて見たように、外部関数を再呼び出すと、最終的に内部が再初期化され、再生成されます.
したがって、比較インスタンスが同じかどうかは、closureのみを使用する場合falseが発生する可能性がありますが、IIFEを適用すると、関数を再呼び出すことができず、返されたオブジェクトのみが返されるため、無条件にtrueが返されます.instance1.setLength(50)の場合、外部関数が新たに生成されたため、外部関数の長さは100に再初期化され、異なる値が現れる.
さらなる検証としてinstance 1.lengthが増加すると、console.log(instance1.length)console.log(instance2.length)の結果もそれに応じて異なることがわかる.
2.すべてのケースが隠匿化(private)を満たす
ここで、instance1.length += 100を実行することは、外部関数のlength値を変更することを意味しないことに留意されたい.
closerオブジェクトのlengthプロパティ値のみが変更され、setLength()メソッドというインタフェースからアクセスしないと、closerオブジェクトから外部関数のlengthにアクセスできません.
従って、どちらの場合も隠匿化、カプセル化を満たすように設計されている.
の最後の部分
これまで,CloserとIIIFEに関する概念を理解するためにSingle Toneというツールを用いてきた.
作者が自ら探し、実施し、まとめたアイデアの文章ですが、間違った内容があれば教えてください、ありがとう(?)
しかし、今回の整理を通じて、私個人はCloser、IIFE、Singletoneについてもっと明確に理解しました.最近は履歴書の整理やアルゴリズムの勉強、自己紹介書の作成などで忙しくてブログを書くのを見過ごし、ブログを書くことやコンセプトを整理する意欲を奮い立たせる良いきっかけになりました!