[Javascript]Closureによるデータ操作とパッケージング


グローバル変数を使用する場合は?

  • 開発者ツールによるデータへの直接アクセス、感染データ等のセキュリティが脆弱
  • let Rollover = {}
    $(function(){
        Rollover.fdno = null
        Rollover.bskno = null
        Rollover.currst = null
    
        injectObj(Rollover,{
            callBskMstByFdidAndCurrst,
            callPositionList,
            callRollover,
            clearSelectedBsk
        })
    })
    →オブジェクトをグローバル変数として宣言し、InjectObject(オブジェクト割り当てカスタマイズ)を使用して関数と変数を処理する

    →対応する画像のように、ブラウザ開発ツールで簡単にデータを変更できる
  • 内部変数に接触しない実施

  • Closureを理解する前に、語彙scopeを理解してください.
    :語彙scopeとは、ソースコードで宣言された変数を考慮して、変数がどこで使用可能かを知る語彙範囲の定義です.
    →簡単に言えば、これは変数のライフサイクルを考えることを意味する(私の観点)
    function init() {
        var name = "blockjjam"; // name is a local variable created by init
        function displayName() { // displayName() is the inner function, a closure
            alert (name); // displayName() uses variable declared in the parent function
        }
        displayName();
    }
    init();
    // init()의 name의 scope는 init함수 안에서만 생존

  • では、露出とは何ですか.
    :これは、一部のデータを操作データの関数に関連付ける有用な技術です.
    :関数と関数宣言の語彙環境の組み合わせによるデータの制御
    function makeFunc() {
      var name = "blockjjam"; (3)
      function displayName() {
        alert(name);
      }
      return displayName;
    }
    
    var myFunc = makeFunc(); // (1)
    //myFunc변수에 displayName을 리턴함
    //유효범위의 어휘적 환경을 유지
    myFunc(); // (2)
    //리턴된 displayName 함수를 실행(name 변수에 접근)
    →例により、
    (1)myFuncはmakeFunc()であり,displayName関数は戻り閉パケットを形成する.
    (2)myFunc()を実行するたびにmakeFunc()のscopeにアクセスしdisplayName関数を実行する
    →displayName makeFunc関数のnameのみ参照!(モジュール作成時のみname参照)
    (3) myFunc.makeFunc()のname変数をnameで変更できますか?
    →実行できません!makeFunc()scopeで返されるdisplayName関数以外はアクセスできません(情報を非表示)
  • Closureでprivateメソッドを模倣する

  • モジュールモード=プライベート関数とアクセス変数の共通関数を定義するようにモジュールを実現する
  • var counter = (function() {
      var privateCounter = 0;
      function changeBy(val) {
        privateCounter += val;
      }
      return {
        increment: function() {
          changeBy(1);
        },
        decrement: function() {
          changeBy(-1);
        },
        value: function() {
          return privateCounter;
        }
      };
    })();
    
    console.log(counter.value()); // logs 0
    counter.increment();
    counter.increment();
    console.log(counter.value()); // logs 2
    counter.decrement();
    console.log(counter.value()); // logs 1
    →上記の例ではcounterを使用してprivateCounter変数に直接アクセスできないため、返されるvalue関数でprivateCounter値を決定できます.

    私たちは露出で外部データの漏洩を阻止します。


  • サンプル環境のコピー
  • Spring boot
  • Thymeleaf
  • jQuery
  • Chrome Devtools

  • 例のClosureコードを見てみましょう
  • var tmp_bskMst = null;
    
    var Rollover = (function(){
        let fdno = null
        let bskno = null
        let currst = null
        let bskMstList = null
    
        /** Async Process  **/
        function callBskMstByFdidAndCurrst(){
            clearSelectedBsk()
            setCurrst($("#sel_currst").val())
            //...
        }
    
        function callPositionList(idx){
            setFdno(bskMstList[idx].fdno)
            setBskno(bskMstList[idx].bskno)
    
            let url = '/order/rollover/list'
            let params = createAsyncJsonParam({fdno, bskno, state: currst})
    				//...
        }
    
        function callRollover(){
            let url = '/order/rollover/toflask' // 명명법 수정 필요
            let params = createAsyncJsonParam({fdno, bskno, state:currst})
            //...
        }
        /** End Async Process  **/
    
        /** Util **/
        function clearSelectedBsk(){
            setFdno(null)
            setBskno(null)
            setCurrst(null)
            setBskMstList(null)
        }
    
        const setFdno = (input_fdno)=>{
            fdno = input_fdno === null? null : parseInt(input_fdno)
        }
    
        const setBskno = (input_bskno)=>{
            bskno = input_bskno === null? null : parseInt(input_bskno)
        }
    
        const setCurrst = (input_currst)=>{
            currst= input_currst === null? null : input_currst;
        }
    
        const setBskMstList = (input_bskMstList)=>{
            bskMstList = input_bskMstList === null? null : input_bskMstList.slice();
        }
        /** End Util **/
    
        return {
            callBskMstByFdidAndCurrst: callBskMstByFdidAndCurrst,
            callPositionList: callPositionList,
            callRollover: callRollover,
            clearSelectedBsk: clearSelectedBsk
        }
    })();
  • 比較のため、クローズコードではなくグローバル変数コードをチェックする
  • let OrderHistory = {}
    $(function (){
        OrderHistory.fdno = null;
        OrderHistory.bskno = null;
        OrderHistory.date = null;
    
    		// 선언한 객체에 함수 객체를 주입해서 사용
        injectObj(OrderHistory, {callFindBskInfo})
        injectObj(OrderHistory, {setOneBskInfo})
        injectObj(OrderHistory, {callFindBskInfo})
    
        // 페이지 로드 시 Order History에 필요한 설정 정보 clear
        OrderHistory.clearSelectedBskInfo()
    })
  • 以上の2つのコードで比較する対象:Rollover VS OrderHistory
  • OrderHistoryを先に確認

  • fdno、date、bsknoは、実際にデータを変更した場合にアクセスできます.

    外部からオブジェクトにアクセスするだけでデータを制御でき、APIサーバにデータを転送することもできますか?

    開発者ツールで扱うように、APIサーバへのデータ転送を確認できます
  • では、Closeを利用したRolloverを見てみましょう

  • ここにも近い財産がありますか?そう言えるけど.
    CallBskMstByFdidAndCurrst、CallPositionList、CallRollover、clearSelection→これらのプログラムはCloseで暴露できる関数です
    var tmp_bskMst = null;
    
    var Rollover = (function(){
        //...
    
        return {
            callBskMstByFdidAndCurrst: callBskMstByFdidAndCurrst,
            callPositionList: callPositionList,
            callRollover: callRollover,
            clearSelectedBsk: clearSelectedBsk
        }
    })();
    上のコードから見ると、Rollover Closerは露出可能な変数のみを返し、外部からアクセス可能な属性のみを提供します.

    上の画像から見ると、
    1つ目は、Rolloverにアクセスできないbskno、fdno、currstなどの変数です.
    2回目の試みでは、RolloverのProperty割り当てと外部に露出した関数の実行を強制します.

    上の結果画像を表示します.
    APIサーバにアクセスしていないため、デバッグ画面もキャプチャされていません.
    (フルスクリーンでは公開できませんが)スクリプトに値情報が正しく含まれていないことがわかります
  • こちら
    :エンクロージャを使用すると、露出可能データと非露出データを区別でき、データをカプセル化できます.
    :キャビネットの注意事項として、露出したデータの実現と管理が重要だと思います
    理由は?グローバル変数でもモジュールでも、実際には、開発者の意図通りに処理するだけであれば問題はなく、逆に非開発者の意図的なアクセスには問題が多い.
    →エンクロージャにおいても、露出データの入力値においても、操作外部データ(tagの属性値など)は検証が必要