Variable Object in JS

14 Oct 2015

  • Variable 와 Execution Context 는 서로 밀접하게 관련되어있다.

  • JS 는 오직 Function Execution Context 내에서만 Isolated scope(격리된 유효범위) 을 가질 수 있다.

      var x = 1; // global variable of the global Execution Context
      function A(){
      
        // function Execution Context
        var y = 2; // local variable of the function Execution Context
      }
      
      console.log(x); // 1
    
      // 유효범위 밖의 접근은 허용하지 않는다.
      console.log(y); // Uncaught ReferenceError: y is not defined
    

  • 즉 JS 는 클래스 기반 언어인 C or C++ 처럼, 블럭 내부에 Isolated scope(격리된 유효범위) 를 가질 수 없다.

      // global execution context
        
      if (1){
          // not isolated scope
          var x = 1;
      }
        
      console.log(x); // 1
        
        
      for (var y = 0; y < 1; y++) {
          // not isolated scope
      }
        
      console.log(y); // 1
    
  • Data declaration(데이터 선언)

    • Variable Object(VO) 는 선언된 데이터(Variable, Function)들이 저장되는 Special Object 이다.

    • 즉 우리가 변수함수를 선언하는 것은, VO 에 새로운 속성을 추가하는것과 동일하다.

      ```javascript
      // global Execution Context
      var x = 1;
      
      function A(){
      
        // function Execution Context
      
      }
      ```
      
    • ECStack 내부

      • VO 는 해당 Execution Context 의 속성으로 표현될 수 있다.<p>

          var ECStack = [
            globalExecutionContext: {
              VO: {
                // Execution Context 진입 시 x 변수는 undefined 로 초기화되며, 
                // A 함수는 Function Object 로 초기화된다.
                x: undefined, 
                A: <reference to function>
              }
            }
          ];
        
    • 선언된 데이터의 종류

      • 변수 선언(VariableDeclaration(VD))<p>

      • 함수 선언(FunctionDeclaration(FD))<p>

      • 함수 매개변수들(Function Formal Parameters)<p>

        ```javascript
          // global Execution Context
          // 변수 선언
          var x = 1;
            
          // 함수 선언
          function A(y){
            
            // function Execution Context
                    
            // 함수 매개변수
            console.log(arguments[0]); // undefined
            
          }
            
          A();
        ```
        
      • ECStack 내부

        ```javascript
          var ECStack = [
            functionExecutionContext: {
              // function execution context 내부 VO 는 AO(활성화 객체)가 그 역활을 대신한다.
              AO(VO): {
                // 전달 받은 함수 매개변수들
                arguments: {
                  0: undefined
                }
                y: undefined
              }
            },
            globalExecutionContext: {
              VO: {
                // 변수 선언식에 의한 초기화
                x: undefined, 
                // 함수 선언식에 의한 초기화
                A: < reference to function > 
              }
            }
          ];
        ```
        
  • VO in Global Execution Context

    • Global Execution Context 의 VO전역 객체를 가리킨다.<p>

    • VO 는 Global Execution Context 진입 전에 생성되며, 프로그램 종료 시 소멸된다.

    • VOthis 키워드를 통해 접근가능하다.

      ```javascript
      // global Execution Context
      var x = 1;
            
      console.log(this); // global object
            
      console.log(x); // 1
      console.log(this.x); // 1
      ```
            
      ![](https://www.dropbox.com/s/giabb54eg1tppkt/87.jpg?dl=1)
      
    • 전역 객체프로그램 레벨의 어떤한 곳에서도 접근 가능하다.

              
        // global Execution Context
        var x = 1;
              
        console.log(this); // global object
        console.log(this.x); // 1
              
        // eval Execution Context
        eval('console.log(this)'); // global object
              
        function A(){
              
            // function Execution Context
            console.log(this); // global object
            console.log(this.x); // 1
        }
              
        A(); // called function object
        
      
    • 전역 객체는 초기화 시 Math, String, Date, parseInt 등의 기본 속성들을 가지며, 자기 자신을 **참조**하는 속성인 window 속성을 갖는다.

      ```javascript
            
      console.log(this.Math); // Math object
            
      console.dir(this.String); // String function object
            
      console.dir(this.parseInt); // parseInt function object
            
      console.log(this); // global object
            
      console.log(this.window); // global object
            
      console.log(this === this.window); // true
      ```		
      
    • 전역 객체 접근 시 접두사 생략이 가능하다.

            // global Execution Context
            var x = 1;
      
            // 접두사가 생략되었다.
            console.log(x); // 1
      
            console.log(this.x); // 1
      
            console.log(window.x); // 1
      
            console.log(this.window.x); // 1
      
  • AO(VO) in Function Execution Context

    • Function Execution Context 내부 VO**직접적인 접근**이 불가능하며, 활성화 객체(AO)가 이 역활을 대신한다.

      • Activation Object(AO)

            function Execution Context VO === AO
        

    • AO함수 호출 후 Function Execution Context 로 진입 시 생성되며, 함수 종료시 소멸된다.

      ```javascript
          
        // global Execution Context
          
        function A(y){
          
          // function Execution Context
          console.log(arguments[0]); // undefined
          console.log(y) // undefined
          
        }
          
        // A 함수를 호출한다.
        A();
      ```
      
    • ECStack 내부

      ```javascript
        var ECStack = [
          // 함수 호출 시 function execution context 가 생성된다. 
          functionExecutionContext: {
            AO(VO): {
              // 함수 매개변수들
              arguments: {
                0: undefined
              }
              y: undefined
            }
          },
          globalExecutionContext: {
            VO: {
              A: <reference to function> // 함수 선언식을 통해 함수 객체로 초기화된다.
            }
          }
        ];
      ```
      
    • arguments 객체 프로퍼티

      ```javascript
      function A(x, y, z) {
          
        // arguments object
        console.dir(arguments);
          
        // 선언된 매개변수의 수
        console.log(A.length); // 3
          
        // 실제 전달된 매개변수의 수
        console.log(arguments.length); // 2
          
        // 함수 자신에 대한 참조
        console.log(arguments.callee === A); // true
          
        // 전달된 매개변수와 arguments object 속성은 서로 공유된다.
        console.log(x === arguments[0]); // true
        console.log(x); // 10
          
        // arguments object 속성을 변경한다.
        arguments[0] = 20;
        console.log(x); // 20
          
        x = 30;
        console.log(arguments[0]); // 30
          
        // 하지만 함수 호출 시 전달되지 않았던, 매개변수 z 속성은 공유되지 않는다.
        z = 40;
        console.log(arguments[2]); // undefined
          
        arguments[2] = 50;
        console.log(z); // 40
      }
          
      A(10, 20); // call function object
      ```
      
  • Execution Context 진입실행 코드 처리 과정

    • Execution Context 안의 코드 실행은 두 가지 기본적인 **단계**로 나뉜다.

      • Execution Context 진입 과정<p>

      • Execution Context 진입 후 실행 코드 처리 과정

    • Execution Context 진입 과정

      • Execution Context 진입 시(실행 코드가 처리 전) VO 의 새로운 속성들이 추가된다.

        • 변수 선언(VariableDeclaration(VD))

          • undefined초기화되는 VO 의 새로운 속성이 추가된다.

            
              // global Execution Context
            
              // Execution Context 진입 시점
              // undefined 로 초기화된다
              console.log(x); // undefined
            
              // 변수 선언
              var x = 1;
            
              // 실행 코드 처리 후
              // 값이 할당된다.
              console.log(this.x); // 1
            
          • Execution Context 진입 시 ECStack 내부

                var ECStack = [
                  globalExecutionContext: {
                    VO: {
                      x: undefined
                    }
                  }
                ];
            
          • 동일한 이름의 변수 선언이 이미 존재할 경우 그 아래의 함수 선언무시된다.

             ```javascript
                      
             // global Execution Context
                    
             // 이 경우 x 는 undefined 가 아닌, function object 로 초기화된다.
             console.log(x); // x function object
                              
             // 변수 선언
             var x = 1;
                    
             // 동일한 이름으로 함수 선언을 한다.
             function x(){
             };
                    
             // 동일한 이름의 함수 선언은 무시된다.
             console.log(x); // 1
             ```
             ![](http://mohwa.github.io/blog/assets/images/posts/20151014/context_2.png)
            
        • 함수 선언(FunctionDeclaration(FD))

          • 함수 객체초기화되는 VO 의 새로운 속성이 추가된다.

            ```javascript
            // global Execution Context
                            
            // Execution Context 진입 시 function object 로 초기화된다.
            console.log(A); // function object
                            
            // 함수 선언식
            function A(){
                  
              // function Execution Context
            }
            ```
            
          • Execution Context 진입 시 ECStack 내부

            ```javascript
            var ECStack = [
              globalExecutionContext: {
                VO: {
                  A: <reference to function> // 함수 선언식을 통한 함수는 function object 로 초기화된다.
                }
              }
            ];
            ```
            
      • 함수 매개변수들(Function Formal parameters)

        • 전달된 매개변수 값을 갖는 VO 의 새로운 속성이 추가된다. 단 값이 전달되지 않았을경우, undefined초기화된다.

          ```javascript
            // global Execution Context
              
            // 함수 선언식
            function A(x, y){
              
              // function Execution Context
              
              console.log(arguments[0]); // 1
              // 값이 전달되지 않은 매개변수는 undefined 로 초기화된다.
              console.log(arguments[1]); // undefined
            }
                        
            // A 함수를 호출한다.
            A(1); 
          ```
          
          ```javascript
            var ECStack = [
              functionExecutionContext: {
                AO(VO): {
                  // function parameters
                  arguments: {
                    0: 1,
                    1: undefined
                  }
                  x: 1,
                  y: undefined
                }
              },
              globalExecutionContext: {
                VO: {
                  A: < reference to function >
                }
              }
            ];
          ```
          
    • Execution Context 진입 후 실행 코드 처리 과정

      • Execution Context 진입 시점에서 초기화된 VO 속성은 실행 코드 처리 후 할당된 값을 가지게 된다.

        ```javascript
        // global Execution Context
                  
        // Execution Context 진입 시점: undefined 로 초기화된다.
        // 실행 코드 처리 후: 1 이 할당된다.
            
        // 변수 선언
        var x = 1;
        ```
        
      • 실행 코드 처리 후 ECStack 내부

          var ECStack = [
            globalExecutionContext: {
              VO: {
                x: 1
              }
            }
          ];
        
  • VO in Eval Execution Context

    • eval 함수에서는 Calling Context 라는 개념이 존재하며, 이것은 eval 함수가 **호출**된 Execution Context 를 가리킨다.<p>

      
        // global Execution Context
      
        // eval 함수가 global execution context 내부에서 호출되었다.
        // 즉 calling context 는 global execution context 를 가리킨다.
        eval('var x = 1;');
      
        console.log(x); // 1
      
        function A(){
      
           // function execution context
      
           // eval 함수가 function execution context 내부에서 호출되었다.
           // 즉 calling context 는 function execution context 를 가리킨다.
           eval('var y = 2;');
      
           console.log(y); // 2
        }
      
        A();
      
    • eval 함수를 통해, 선언된 변수, 함수는 Calling Context 내부 VO 에 영향을 준다.(즉 Calling Context 내부 VO 의 속성으로 할당된다)<p>

    • eval 함수로 전달된 실행 코드는 생성된 Eval Execution Context 내부에서 처리된다.<p>

    • 해당 VO 는 Eval Execution Context 진입 시 생성되며, eval 함수 종료 시 소멸된다.

      • Global Execution Context 에서의 eval 함수

        ```javascript

        // global Execution Context

        // calling context 는 global execution context 를 가리킨다.

        // eval 함수를 통해 생성된 x 속성은 해당 calling context 내부 VO 에 영향을 준다. eval(‘var x = 1’);

        console.log(x); // 1 ```

      • ECStack 내부

        
          var ECStack = [
            evalExecutionContext: {
              VO: {
                x: 1
              }
            },
            callingContext: globalExecutionContext,
            globalExecutionContext: {
              VO: {
                // eval 함수로 전달된 실행 코드로 인해, calling context 내부 VO 가 영향받는다.
                x: 1
              }
            }
          ];
        
      • Function Execution Context 에서의 eval 함수

        
          // global execution context
        
          function A() {
        
              // function execution context
        
              // calling context === function execution context
        
              // x 지역 변수르 선언한다.
              var x = 1;
        
              // eval 함수를 통해, 변수를 선언한다.
              eval('var y = 2;');
        
              console.log(x); // 1
        
              // y 속성은 calling context 내부 VO 에 영향을 준다.
              console.log(y); // 2
          }
        
          A();
        
      • ECStack 내부

        
          var ECStack = [
            evalExecutionContext: {
              VO: {
                y: 2
              }
            },
            // 호출 문맥
            callingContext: <A> functionExecutionContext,
            <A> functionExecutionContext: {
              AO(VO): {
                x: 1,
                // eval 함수로 전달된 실행 코드로 인해, calling context 내부 VO 가 영향받는다.
                y: 2
              }
            },
            globalExecutionContext: {
              VO: {
                A: < reference to function >
              }
            }
          ];
        
    • ES5 strict-mode 에서의 eval 함수는 Calling Context 내부 VO 에 영향을 주지 않으며, 코드를 지역 샌드박스(local sandbox)에서 평가하게된다.

      
        'use strict';
      
        // global Execution Context
      
        // calling context 는 global Execution Context 를 가리킨다.
      
        // x 변수를 선언한다.
        var x = 1;
      
        // eval 함수를 통해, 선언된 변수는 해당 calling context 에 영향을 주지않으며, local sandbox 안에서 평가하게된다.
        eval('var y = 2;');
      
        console.log(x); // 1
      
        // calling context 내부 VO 에 영향을 주지 않는다.
        // local sandbox 외부에서 y 속성을 접근할 수 없다.
        console.log(y); // Uncaught ReferenceError: y is not defined
      
    • ECStack 내부

        var ECStack = [
          // local sand box
          evalExecutionContext: {
            VO: {
              y: 2
            }
          },
          // 호출 문맥
          callingContext: globalExecutionContext,
          globalExecutionContext: {
            VO: {
              // y 속성이 추가되지 않았다(즉 해당 calling context 내부 VO 에 영향을 주지 않는다)
              x: 1
            }
          }
        ];
      

참고 URL

comments powered by Disqus