Variable Object in JS

October 14, 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 에 새로운 속성을 추가하는것과 동일하다.

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

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

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

      • 변수 선언(VariableDeclaration(VD))

      • 함수 선언(FunctionDeclaration(FD))

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

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

          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전역 객체를 가리킨다.

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

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

      // global Execution Context
      var x = 1;
      
      console.log(this); // global object
      
      console.log(x); // 1
      console.log(this.x); // 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 속성을 갖는다.

      
      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 로 진입 시 생성되며, 함수 종료시 소멸된다.

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

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

      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 진입 과정

      • 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
                  }
                }
              ];
          • 동일한 이름의 변수 선언이 이미 존재할 경우 그 아래의 함수 선언무시된다.

            
            // global Execution Context
            
            // 이 경우 x 는 undefined 가 아닌, function object 로 초기화된다.
            console.log(x); // x function object
            
            // 변수 선언
            var x = 1;
            
            // 동일한 이름으로 함수 선언을 한다.
            function x(){
            };
            
            // 동일한 이름의 함수 선언은 무시된다.
            console.log(x); // 1

        • 함수 선언(FunctionDeclaration(FD))

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

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

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

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

            // global Execution Context
          
            // 함수 선언식
            function A(x, y){
          
              // function Execution Context
          
              console.log(arguments[0]); // 1
              // 값이 전달되지 않은 매개변수는 undefined 로 초기화된다.
              console.log(arguments[1]); // undefined
            }
            
            // A 함수를 호출한다.
            A(1); 
            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 속성은 실행 코드 처리 후 할당된 값을 가지게 된다.

        // 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 를 가리킨다.

      
      // 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 의 속성으로 할당된다)

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

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

      • Global Execution Context 에서의 eval 함수

        
        // 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


Profile picture

Written by mohwa