Function in JS

15 Oct 2015

  • JS 의 다양한 함수 식

          
      // global execution context
      
      // 함수 선언식의 경우, 해당 execution context 진입 시, VO 의 새로운 속성으로 추가되며, function object 로 초기화된다.
      console.log(A); // function object
        
      // 함수 선언식(FD)
      function A(){
          // function execution context
          console.log(this); // global object
      };
        
      // 함수 표현식의 경우, 해당 execution context 진입 시, VO 의 새로운 속성으로 추가되지않으며, 
      // 초기화된 undefined 는 B 변수 선언식에 의해 초기화된것이다.
      console.log(B); // undefined
        
      // 함수 표현식(FE)
      var B = function () {
          // function execution context
          console.log(this); // global object
      };
        
      // 즉시 실행 함수(IIFE)(함수 표현식 중 하나)
      (function C(){
          // function execution context
          console.log(this); // null ==> global object
      })();
        
      // 함수 표현식의 경우, 해당 execution context 진입 시, VO 의 새로운 속성으로 추가되지않으며, 
      // 즉시 실행 함수의 경우, 함수 실행이 끝난 후 바로 소멸된다
      console.log(C); // Uncaught ReferenceError: C is not defined
    
  • 함수 선언식(Function Declaration(FD))

    • A 함수 선언

      ```javascript
      // A 함수 선언
      function A(){
        // function execution context
      };
      ```
      
      • FD 는 함수 정의를 나타내는 문장으로 해석되며, 수행결과가 존재하지 않는다.

        ```javascript
        function A(){}.length // Uncaught SyntaxError: Unexpected token .
        ```
        
      • FD 는 해당 Execution Context 진입 시, VO 의 새로운 속성으로 추가되며, function object 로 초기화 된다.(이 현상을 보통 HoistingCompiler Lift 라 부른다)

        ```javascript
        
        // global execution context
        
        // execution context 진입 시 function object 로 초기화된다.
        console.log(A); // A function object
        
        function A(){
        };
           
        ```
        
    • global execution context 내부 선언

        // global execution context
      
        function A(){
        };
      
    • ECStack 내부

        var ECStack = [
          globalExecutionContext: {
            VO: {
              A: <reference to function>
            }
          }
        ];
      
    • global or function execution context 내부 선언

      
        // global execution context
      
        // global execution context 의 VO 속성으로 추가된다.
        function A(){
      
          // function execution context
      
          // 내부 함수
          // function execution context 의 AO(VO) 속성으로 추가된다.
          function B(){
            // function execution context
          }
        };
      
        A();
      
    • ECStack 내부

        var ECStack = [
          <A> functionExecutionContext: {
            AO(VO): {
              // function execution context 의 AO(VO) 속성으로 추가된다.
              B: <reference to function>
            },
            // 함수 호출 시 생성되는 Scope Chain
            Scope(Scope Chain): [
              AO(VO): {
                B: <reference to function>
              },
              globalExecutionContext.VO: {
                A: < reference to function >
              }
            ]
          },
          globalExecutionContext: {
            VO: {
              // global execution context 의 VO 속성으로 추가된다.
              A: <reference to function>
            },
            Scope(Scope Chain): [
              globalExecutionContext.VO
            ]
          }
        ];
      
  • 함수 표현식(Function Expression(FE))

    • FE 는 기본적으로 표현식 위치에만 정의할 수 있다.

    • FE 는 해당 Execution Context 진입 시, VO 의 새로운 속성으로 추가되지않으며, 초기화된 undefined 는 A 변수 선언식에 의해 초기화된것이다.

      ```javascript
            
      // 함수 표현식이 아닌, A 변수 선언식에 의해 undefined 로 초기화된다.
      console.log(A); // undefined
          
      var A = function(){};
            
      // 실행 코드 처리 후 function object 가 할당된다.
      console.dir(A); // function object
      ```
      
    • FE 는 함수 데이터로 해석되며, 수행 결과가 존재한다.

      ```javascript
         // 괄호 연산자를 통한 함수 표현식
        (function A(){}).length;
              
        console.log((function A(){}).length); // 0
      ```	
      
    • FE선택적 이름을 가질 수 있다.

      • 익명 함수 표현 식(AFE(Anonymous Function Expression))

      • 기명 함수 표현 식(NFE(Named Function Expression))

                  
          // 익명 함수 표현식
          var A = function(){};
                
          // 기명 함수 표현식
          var B = function _B(){};
                
        
      • NFE의 함수 이름은 VO 속성으로 추가되지 않는다.

        ```javascript
            
        // 기명 함수 표현식
        var A = function _A(){}; 
            
        console.log(this.A); // function object
        console.log(this._A); // undefined
        ```
        
      • NFE의 함수 이름은 함수 내부에서만 접근 가능하다.

        ```javascript
            
        var A = function _A(){
          console.log(_A); // function object
        };
          
        A();
            
        console.log(this.A); // function object
        console.log(this._A); // undefined
        ```
        
    • 그룹화 연산자의 활용

      • FD 와 그룹화 연산자의 사용은 동일하다.

        ```javascript
            
          // JS 파서는 A 함수 선언식과 1 표현식을 감싸는 그룹화 연산자로 해석한다.
          // 즉 error 가 발생하지 않는다.
          function A(){
            
          }(1); // 1
            
          function A(){
            
          }    
            
          (1); // 1
        ```
        
      • 즉시 실행 함수 표현식(Immediately-Invoked Function Expression(IIFE))

        • 즉시 실행 함수는 FE 중 하나이다.<p>

        • 그룹화 연산자를 통해 파서가 FE해석하도록 만들 수 있다.<p>

        • 그룹화 연산자를 통해 생성된 함수는 함수 실행이 끝난 후 **바로 소멸**된다.<p>

          • FEVO 의 속성으로 추가되지 않는다.<p>

          • VO 에 추가되지 않는다는 말은, 메모리를 가용성이 좋다는 말과 같다.<p>

        • 함수를 실행 후 바로 소멸 시키는 경우, 사용하면 좋다.<p>

        • 하지만 이 말은 생성된 함수재사용이 불가능 하다는 말과 같다.(잘못 설계하면, 코드 가독성이 떨어질 위험이 있다;;;)<p>

          ```javascript
                      
          // 즉시 실행 함수를 호출하는 두 가지 방법
          (function A(x){
              
            console.log(x); // 1
              
          })(1);
                      
          (function A(x){
              
            console.log(x); // 1
              
          }(1));
                        
          ```
          
          • 그 밖에 방법(표현식이 가능할 뿐 거의 사용되지는 않는다(특별한 경우가 아니라면, 사용하지 않는것이 좋다))

            ```javascript
            1, function A(x){
                    
              console.log(x); // 1
                    
            }(1);
                    
            !function B(y){
                    
              console.log(y); // 2
            }(2);			
            ```
            
          • IIFE 응용

            • apply 메서드를 통한 this 값 초기화

                              
                // global execution context
              
                (function(){
              
                  // function execution context
              
                  console.log(this); // object Object
              
                }).apply({});
              
            • JS Singleton 구현

              
                // global execution context
              
                var $ = (function(){
              
                    // 익명 함수 표현식 내부
                    // function execution context
                    var instance = null;
              
                    function $(){
              
                        // $ 함수 선언식 내부
                        // function execution context
              
                        // 만약 instance 변수에 할당된 this 값이 있다면, 그 값을 반환한다.
                        if (!instance) instance = this;
              
                        return instance;
                    }
              
                    return $;
              
                }());
              
                var obj1 = new $();
                var obj2 = new $();
              
                console.log(obj1 === obj2); // ture
              
            • JQuery Framework 구조생성

              
                  var $ = (function(){
              
                      function $(selector){
                          return new init(selector);
                      };
              
                      function init(selector){
              
                          selector = selector || '';
              
                          var elems = document.getElementById(selector) || document.getElementsByTagName(selector);
              
                          if (elems.length){
              
                              for (var n in elems) {
              
                                  var elem = elems[n];
              
                                  if (elem.nodeName) this[n] = elems[n];
                              };
                          }
              
                          return this;
                      };
              
                      init.prototype = {
              
                          get: function(idx){
              
                              idx = idx || 0;
              
                              return this[idx] || undefined;
                          }
                      };
              
                      $.get = function(){
                          console.log('ajax get');
                      };
                      $.post = function(){
                          console.log('ajax post');
                      };
              
                      return $;
              
                  })();
              
                  console.log($('title')); // object Object
              
                  console.log($('title')[0]); // title elem
                  console.log($('title').get(0)); // title elem
              
                  console.log($('meta')[0]); // meta elem
                  console.log($('meta').get(0)); // meta elem
              
                  console.log($('span')[0]); // undefined
                  console.log($('span').get(1)); // undefined
              
                  $.get(); // ajax get
                  $.post(); // ajax post
              
    • 그룹화 연산자를 사용하지 않는 IIFE

      • FE 는 반드시 FE 위치에 있어야 한다.

        • FEFE 위치에 있을 경우, 파서는 실행 코드 처리시, 이것이 실행 가능하다는 것을 알고 있다.

          ```javascript
          
            var A = function(x){
              console.log(x); // 1
            }(1);
          
            var B = {
          
              // 상황에 따른 초기화 값을 할당할때 유용하게 사용할 수 있다.
              x: function(y){
                return y ? true : false;
              }(1)
            };
          
            console.log(B.x); // true
          ```
          
comments powered by Disqus