• javascript 

    1. 글에 대해

    • 모든 결과는 Chrome 브라우저를 통해 테스트된 결과입니다.

    2. const 키워드

    • const 키워드는 let 키워드와 유사한 언어 매커니즘을 가지고있다.

    3. ES5 & const

    • Object.defineProperty or create 메서드를 통해, 읽기전용 속성을 생성할 수 있다(단 일반적인 방법으로 (속성)재 할당const 키워드와 같은 예외가 발생하지는 않는다)

      ```javascript
      // global ec
        
      // globalEC.VO 객체에 읽기 전용 속성을 생성한다.(이떄 생성된 a 속성은 변수가 아니다)
      Object.defineProperty(this, 'a', {
          writable: false,
          value: 1
      });
        
      // VO 객체의 a 속성 값을 변경한다.
      a = 2;
        
      // 읽기 전용 속성으로 값이 변경되지않는다.
      console.log(a); // 1
        
      // writable 속성의 기본값은 false 이며, 반드시 속성을 정의할 필요는 없다.
      Object.defineProperty(this, 'b', {
      //    writable: false,
          value: 1
      });
        
      // VO 객체의 b 속성 값을 변경한다.
      b = 2;
        
      // 읽기 전용 속성으로 값이 변경되지않는다.
      console.log(b); // 1
        
        
      // global ec
        
      (function A(){
        
          // A function ec
        
          // AO 객체는 직접 접근할 수 없다. 즉 AO 객체의 읽기 전용 속성을 생성할 수 없다는 단점이 존재한다.
        
          // 하지만 ES6 의 const 키워드를 통해서는 생성 가능하다.
          const a = 1;
        
          console.log(a); // 1
        
      })();
        
        
      // obj 객체에 읽기 전용 속성 생성하기
      var obj = {};
        
      // Object.defineProperty 메서드를 통해 생성하는 방법은 아래와 같다.
      Object.defineProperty(obj, 'x', {
          writable: false,
          value: 1
      });
        
      // 속성값을 변경한다
      obj.x = 2;
        
      // 읽기 전용 속성으로 값이 변경되지않는다.
      console.log(obj.x); // 1
        
        
      // Object.create 메서드를 통해 생성하는 방법은 아래와 같다.
      var obj2 = Object.create(Object.prototype, {
          x: {
              writable: false,
              value: 1
          }
      });
        
      // 속성값을 변경한다
      obj2.x = 2;
        
      // 읽기 전용 속성으로 값이 변경되지않는다.
      console.log(obj2.x); // 1
        
        
      // 인스턴스의 속성을 읽기 전용으로 초기화하는 방법은 아래와 같다.
      function A(){
        
          if (!(this instanceof A)) return;
        
          // 읽기 전용
          Object.defineProperty(this, 'x', {
              writable: false,
              value: 1
          });
        
          // 읽기/쓰기
          Object.defineProperty(this, 'y', {
              writable: true,
              value: 1
          });
      }
        
      // 새로운 인스턴스를 생성한다.
      var newAObject = new A;
        
      // 생성된 인스턴스의 속성값을 변경한다
      newAObject.x = 2;
        
      // 생성된 인스턴스의 속성값을 변경한다
      newAObject.y = 2;
        
      // 읽기 전용 속성으로 값이 변경되지않는다.
      console.log(newAObject.x); // 1
        
      // 읽기/쓰기 속성이며, 변경된 값인 2를 반환한다.
      console.log(newAObject.y); // 2
      ```
      
    • Object.defineProperty 메서드를 통해, 읽기 전용 속성을 재 정의 시, 재 정의대한 예외가 발생하게된다.

      ```javascript
      Object.defineProperty(this, 'a', {
          writable: false,
          value: 1
      });
        
      // 단 Object.defineProperty 메서드를 통해 읽기 전용 속성을 재 정의 시, 재 정의에 대한 예외가 발생하게된다.
      try{
        
          Object.defineProperty(this, 'a', {
              writable: false,
              value: 2
          });
      }
      catch(e){
          // Cannot redefine property: a
          console.log(e.message);
      }
      ```      
      

    4. ES6 & const

    • const 키워드를 통해 선언된 상수는, 블럭 범위의 Isolated Scope(격리된 유효범위) 를 갖게된다.

            
        {
            // block scope
            
            // const 키워드를 통한 변수 선언
            const a = 1;
        }
            
        if (true){
            const b = 2;
        }
            
        switch (1){
            case 1:
                const c = 3;
                break;
        }
            
        for (var d = 0; d < 3; d++){
            const _d = d;
            console.log(_d); // 0, 1, 2
        }
            
            
        const e = 4;
            
            
        try {
            // 실행 코드 처리 시, 블록 범위에 선언된 a 상수는 선언되지 않았다는 예외가 발생하게 된다.
            console.log(a);
        }
        catch(e){
            // a is not defined
            console.log(e.message);
        }
            
        try {
            // 실행 코드 처리 시, 블록 범위에 선언된 b 상수는 선언되지 않았다는 예외가 발생하게 된다.
            console.log(b);
        }
        catch(e){
            // b is not defined
            console.log(e.message);
        }
            
        try {
            // 실행 코드 처리 시, 블록 범위에 선언된 c 상수는 선언되지 않았다는 예외가 발생하게 된다.
            console.log(c);
        }
        catch(e){
            // c is not defined
            console.log(e.message);
        }
            
        try {
            // 실행 코드 처리 시, 블록 범위에 선언된 d 상수는 선언되지 않았다는 예외가 발생하게 된다.
            console.log(_d);
        }
        catch(e){
            // _d is not defined
            console.log(e.message);
        }
            
        console.log(e); // 4
      
    • const 키워드를 통해 선언된 상수유효 범위는 자신을 포함한 블럭 및 그 내부 블럭까지 유효하다.

        {
            const a = 1;
            
            {
                const b = 2;
            
                {
                    const c = 3;
            
                    {
                        const d = 4;
            
                        // 선언된 상수의 유효 범위는 자신을 포함한 블럭 및 그 내부 블럭까지 유효하다
                        console.log(a, b, c, d); // 1, 2, 3, 4
                    }
                }
            }
            
            console.log(a); // 1;
            
            // 해당 블럭 Scope 에서는 b 상수에 접근할 수 없다.
            try{
                console.log(b);
            }
            catch(e){
                // b is not defined
                console.log(e.message);
            }
            
        }
      
    • 동일 블럭 범위에서, 동일한 식별자 이름으로 상수를 재 선언예외가 발생하게된다.

        // 동일 블럭 범위에서, 동일한 식별자 이름으로 변수를 재 선언시, 아래와 같은 예외가 발생하게된다.
            
        const a = 1;
        // Uncaught SyntaxError: Identifier 'a' has already been declared
        const a = 2;
            
        const obj = {};
        const obj = {}; // Uncaught SyntaxError: Identifier 'obj' has already been declared
            
            
        {
            const b = 1;
            // Uncaught SyntaxError: Identifier 'b' has already been declared
            const b = 2;
        }
            
        if (true){
            const i = 1;
            const i = 2; // Uncaught SyntaxError: Identifier 'i' has already been declared
        }
            
        (function A(){
            const c = 1;
            const c = 2; // Uncaught SyntaxError: Identifier 'c' has already been declared
        })();
            
            
        // 다른 식별자 이름으로 선언 시 예외가 발생하지 않는다.
        {
            const c = 1;
            const d = 2;
            
            console.log(d); // 2
        }
      
    • const 키워드를 통해 선언된 상수 재 할당 시 예외가 발생하게 된다.

        const a = 1;
            
        // Uncaught TypeError: Assignment to constant variable.
        a = 2;
            
        // 당연한 말이겠지만, 선언된 obj 객체의 속성까지 상수 범위가 적용되지는않는다.
        const obj = {x: 1};
            
        // x 속성은 읽기/쓰기 속성으로 선언되어있다.
            
        // Object {value: 1, writable: true, enumerable: true, configurable: true}
        console.log(Object.getOwnPropertyDescriptor(obj, 'x')); 
            
            
        obj.x = 2;
            
        console.log(obj.x); // 2
            
      
    • const 키워드를 통해 선언된 상수EC 진입 및 실행 코드 처리 후에도 VO 의 새로운 속성으로 추가되지않는다..

        // global ec 진입 시 VO 의 새로운 속성으로 추가되지않는다.
        try {
            console.log(a); // a is not defined
        }
        catch(e){
            console.log(e.message);
        }
            
        const a = 1;
            
        // 할당된 값을 반환한다.
        console.log(a); // 1
            
        // 실행 코드 처리후에도 VO 의 새로운 속성으로 추가되지않는다.
        console.log(window.a); // undefined
      
    • 동일 VO(AO) 범위에서, 동일한 식별자 이름으로 변수(or 함수) 선언예외가 발생하게 된다.(단 const 키워드를 통해 선언된 변수는 VO 의 속성으로 추가되지않는다)

            
        // 테스트 1
        // global ec
        const a = 1;
        // globalEC.VO.a
        var a; // Uncaught SyntaxError: Identifier 'a' has already been declared
            
            
        // 테스트 2
        // global ec
        const a = 1;
        {
            // globalEC.VO.a
            var a; // Uncaught SyntaxError: Identifier 'a' has already been declared
        }
            
        // 테스트 3
        // global ec
        const a = 1;
            
        if (true){
            // globalEC.VO.a
            var a; // Uncaught SyntaxError: Identifier 'a' has already been declared
        }
            
        // 테스트 4
        // global ec
        const a = 1;
            
        // globalEC.VO.a
        // Uncaught SyntaxError: Identifier 'a' has already been declared
        function a(){
            
            // a function ec
        }
            
        // 테스트 5
        // global ec
        const a = 1;
            
        (function A(){
            
            // A function ec
            
            // 이 경우 a 변수는 globalEC.VO 의 속성으로 추가되며, 마찬가지로 예외가 발생하게된다.
            
            a; // Uncaught SyntaxError: Identifier 'a' has already been declared
        })();
            
            
        // 테스트 6
        // global ec
        (function A(){
            
            // function ec
            
            const a = 1;
            
            // 이 경우 a 변수는 AFunctionEC.AO 의 속성으로 추가되며, 마찬가지로 예외가 발생하게된다.
            var a;
        })();
            
            
        // 테스트 7
        // global ec
        const a;
            
        (function A(){
            
            // A function ec
            
            // 이 경우 a 변수는 AFunctionEC.AO 의 속성으로 추가되며, 예외가 발생하지않는다.
            var a;
            
            console.log(a); // undefined
        })();
      
      
    • 루프(for, while 등)문 내부에서 (const 키워드를 통해)선언된 변수는, 비동기 함수안에서 각기 다른 상수참조하게된다.(즉 각 루프는 서로 다른 상수(값)를 가지게 된다)

            
        // global scope
        for (var i = 0; i < 10; i++) {
            
            // block scope
            
            // 루프문 내부에 const 키워드를 통해 선언된 상수
            const _i = i;
            
            window.setTimeout(function() {
            
                // 이 경우 _i 상수는 각기 다른 상수 값을 참조하게된다.
                console.log(_i); // 0 ~ 9
            
                // var 키워드를 통해 선언된 i 변수는, 함수 Scope Chain 매커니즘에 의해 최종 증감값인 10을 참조하게된다.
                console.log(i); // 10
            });
        }
            
        console.log(i); // 10;
            
            
        var i = 4;
        while (i) {
            
            // block scope
            
            const _i = i;
            // const 키워드를 통해 상수를 선언한다.
            window.setTimeout(function() {
                // 이 경우 _i 상수는 각기 다른 변수 값을 참조하게된다.
                console.log(_i); // 4 ~ 1
            });
            
            i--;
        }
            
        // ES5 를 통한 구현은 아래와 같다.
        for (var i = 0; i < 10; i++){
            
            // 루프 순회 시 (읽기 전용 속성)재 정의에 대한 예외가 발생하게 된다.
            
            // Uncaught TypeError: Cannot redefine property: _i
            Object.defineProperty(this, '_i', {
                writable: false,
                value: i
            });
            
            window.setTimeout(function(){
                console.log(_i); // 0 ... error
            });
        }
           
      
    • eval 함수를 통해, 선언된 상수는 local sandbox 안에서 평가된다.

            
        eval('const i = 1');
            
        try{
            i;
        }
        catch(e){
            console.log(e.message); // i is not defined
        }
           
      

    관련 URL

    Read more


  • javascript 

    1. 글에 대해

    • 모든 결과는 Chrome 브라우저를 통해 테스트된 결과입니다.

    2. ES5 & var

    • var 키워드를 통한 변수 선언

      • ES5 는 오직 function execution context 내부에서만 Isolated Scope(격리된 유효범위) 를 가질 수 있다.

        // global ec
        var a = 0;
        
        function A(){
        
            // A function ec
        
            // AFunctionEC.AO.a
            var a = 1;
        
            (function B(){
        
                // B function ec
        
                var a = 2;
        
                // BFunctionEC.AO.a
                console.log(a); // 2
            })()
        
            console.log(a); // 1
        }
        
        // globalEC.VO.a
        console.log(a); // 0
        
        A();
        
      • ES5클래스 기반 언어인 C or C++ 처럼, 블럭 내부에 Isolated Scope(격리된 유효범위) 를 가질 수 없다.

        // global ec
        var a = 0;
        
        if (true){
        
            // if 문 블럭 내부의 local context 를 갖지않는다.
            // 즉 선언된 변수 a 는 다른 값(1)으로 대치된다.
            var a = 1;
        }
        
        // globalEC.VO.a
        console.log(a); // 1
        

    3. ES6 & let

    • let 키워드를 통해 선언된 변수는, 블럭 범위의 Isolated Scope(격리된 유효범위) 를 갖게된다.

            
        // global scope
            
        {
            // block scope
            
            // let 키워드를 통한 변수 선언
            let a = 1;
        }
            
        if (true){
            let b = 2;
        }
            
        switch (1){
            case 1:
                let c = 3;
                break;
        }
            
        for (let d = 0; d < 3; d++){
          console.log(d); // 0, 1, 2
        }
                  
            
        let e = 4;
            
            
        try {
            // 실행 코드 처리 시, 블록 범위에 선언된 a 변수는 선언되지 않았다는 예외가 발생하게 된다.
            console.log(a);
        }
        catch(e){
            // a is not defined
            console.log(e.message);
        }
            
        try {
            // 실행 코드 처리 시, 블록 범위에 선언된 b 변수는 선언되지 않았다는 예외가 발생하게 된다.
            console.log(b);
        }
        catch(e){
            // b is not defined
            console.log(e.message);
        }
            
        try {
            // 실행 코드 처리 시, 블록 범위에 선언된 c 변수는 선언되지 않았다는 예외가 발생하게 된다.
            console.log(c);
        }
        catch(e){
            // c is not defined
            console.log(e.message);
        }
            
        try {
            // 실행 코드 처리 시, 블록 범위에 선언된 d 변수는 선언되지 않았다는 예외가 발생하게 된다.
            console.log(d);
        }
        catch(e){
            // d is not defined
            console.log(e.message);
        }
            
        console.log(e); // 4
      
    • let 키워드를 통해 선언된 변수유효 범위는 자신을 포함한 블럭 및 그 내부 블럭까지 유효하다.

        {
            let a = 1;
            
            {
                let b = 2;
            
                {
                    let c = 3;
            
                    {
                        let d = 4;
            
                        // 선언된 변수의 유효 범위는 자신을 포함한 블럭 및 그 내부 블럭까지 유효하다
                        console.log(a, b, c, d); // 1, 2, 3, 4
                    }
                }
            }
            
            
            console.log(a); // 1;
            
            // 해당 블럭 Scope 에서는 b 변수에 접근할 수 없다.
            try{
                console.log(b);
            }
            catch(e){
                // b is not defined
                console.log(e.message);
            }
            
        }
      
    • 동일 블럭 범위에서, 동일한 식별자 이름으로 변수를 재 선언예외가 발생하게된다.

        // 동일 블럭 범위에서, 동일한 식별자 이름으로 변수를 재 선언시, 아래와 같은 예외가 발생하게된다.
            
        let a;
        // Uncaught SyntaxError: Identifier 'a' has already been declared
        let a;
            
        {
            let b;
            // Uncaught SyntaxError: Identifier 'b' has already been declared
            let b;
        }
            
        if (true){
            let i;
            let i; // Uncaught SyntaxError: Identifier 'i' has already been declared
        }
            
        (function A(){
            let c;
            let c; // Uncaught SyntaxError: Identifier 'c' has already been declared
        })();
            
        // 다른 식별자 이름으로 선언 시 예외가 발생하지 않는다.
        {
            let c;
            let d;
            
            console.log(d); // undefined
        }
      
    • let 키워드를 통해 선언된 변수EC 진입 및 실행 코드 처리 후에도 VO 의 새로운 속성으로 추가되지않는다.

      • 변수(a)가 Scope 에는 존재하지만, 초기화 되지않는 이 단계를 가리켜 Temporal Dead Zone(일시적 사각 지대)라고 부르며, 관련 예외 또한 모두 구현되어있다.

          // global ec 진입 시 VO 의 새로운 속성으로 추가되지않는다.
          try {
            console.log(a); // a is not defined
          }
          catch(e){
            console.log(e.message);
          }
        
          let a = 1;
        
          // 할당된 값을 반환한다.
          console.log(a); // 1
        
          // 실행 코드 처리후에도 VO 의 새로운 속성으로 추가되지않는다.
          console.log(window.a); // undefined
        
    • 동일 VO(AO) 범위에서, 동일한 식별자 이름으로 변수(or 함수) 선언예외가 발생하게 된다.(단 let 키워드를 통해 선언된 변수는 VO 의 속성으로 추가되지않는다)

            
        // 테스트 1
        // global ec
        let a;
        // globalEC.VO.a
        var a; // Uncaught SyntaxError: Identifier 'a' has already been declared
            
            
        // 테스트 2
        // global ec
        let a;
        {
            // globalEC.VO.a
            var a; // Uncaught SyntaxError: Identifier 'a' has already been declared
        }
            
        // 테스트 3
        // global ec
        let a;
            
        if (true){
            // globalEC.VO.a
            var a; // Uncaught SyntaxError: Identifier 'a' has already been declared
        }
            
        // 테스트 4
        // global ec
        let a;
            
        // globalEC.VO.a
        // Uncaught SyntaxError: Identifier 'a' has already been declared
        function a(){
            
            // a function ec
        }
            
        // 테스트 5
        // global ec
        let a;
            
        (function A(){
            
            // A function ec
            
            // 이 경우 a 변수는 globalEC.VO 의 속성으로 추가되며, 마찬가지로 예외가 발생하게된다.
            
            a; // Uncaught SyntaxError: Identifier 'a' has already been declared
        })();
                  
               
        // 테스트 6            
        // global ec
        (function A(){
            
            // function ec
                
            let a;
            
            // 이 경우 a 변수는 AFunctionEC.AO 의 속성으로 추가되며, 마찬가지로 예외가 발생하게된다.
            var a;
        })();
               
      
        // 테스트 7
        // global ec
        let a;
            
        (function A(){
            
            // A function ec
            
            // 이 경우 a 변수는 AFunctionEC.AO 의 속성으로 추가되며, 예외가 발생하지않는다.
            var a;
            
            console.log(a); // undefined
        })();
      
      
    • 루프(for, while 등)문 내부에서 (let 키워드를 통해)선언된 변수는, 비동기 함수안에서 각기 다른 변수참조하게된다.(즉 각 루프는 서로 다른 변수(값)를 가지게 된다)

            
        // global scope
            
        // 루프 문 밖에서 let 키워드를 통해 선언된 변수
        let i = 0;
            
        for (;i < 10; i++) {
            
            // block scope
            window.setTimeout(function() {
                // 이 경우 i 변수는 최종 증감값인 10 을 반환하게된다.
                console.log(i); // 10
            });
        }
            
        // global scope
            
        // 루프문 내부에 let 키워드를 통해 선언된 변수
        for (let i = 0; i < 10; i++) {
            
            // block scope
            window.setTimeout(function() {
                // 이 경우 i 변수는 각기 다른 변수 값을 참조하게된다.
                console.log(i); // 0 ~ 9
            });
        }
            
        // global scope
        for (var i = 0; i < 10; i++) {
            
            // block scope
            
            // 루프문 내부에 let 키워드를 통해 선언된 변수
            let _i = i;
            
            window.setTimeout(function() {
                // 이 경우 _i 변수는 각기 다른 변수 값을 참조하게된다.
                console.log(_i); // 0 ~ 9
                // var 키워드를 통해 선언된 i 변수는, 함수 Scope Chain 매커니즘에 의해 최종 증감값인 10을 참조하게된다.
                console.log(i); // 10
            });
        }
            
        console.log(i); // 10;
            
            
        var i = 4;
        while (i) {
            
            // block scope
            
            let _i = i;
            // let 키워드를 통해 변수를 선언한다.
            window.setTimeout(function() {
                // 이 경우 _i 변수는 각기 다른 변수 값을 참조하게된다.
                console.log(_i); // 4 ~ 1
            });
            
            i--;
        }
            
        // 위 결과를 ES5 를 통해 구현한 방법은 아래와 같다.
            
        for (var i = 0; i < 10; i++){
            
            window.setTimeout(function(i){
            
                // Function.AO.i
                // bind 함수를 통해 바인딩된 AO.i 값을 참조하게 된다.
                console.log(i); // 0 ~ 9
            }.bind(null, i));
        }
            
        // 최종 증감값인 10을 반환하게된다.
        console.log(i); // 10
           
      
    • eval 함수를 통해, 선언된 변수(or 함수)는 local sandbox 안에서 평가된다.

            
        eval('let i');
            
        try{
            i;
        }
        catch(e){
            console.log(e.message); // i is not defined
        }
           
      

    관련 URL

    Read more


  • javascript 

    1. 글에 대해

    • 이 글은 ES5ES6 Arrow Function 안에서 this 값이 어떤식으로 평가되는지에 대한 내용을 다루고있다.

    • 또한 모든 결과는 Chrome 브라우저를 통해 테스트된 결과입니다.

    2. ES5 & this

    • this 값 초기화 테스트

      ```javascript
      // A 함수 객체를 선언한다.
      function A() {
        
        
          function B() {
              // this 는 undefined 로 초기화되며, undefined 는 this 로 평가될 수 없으므로, 암묵적으로 global Object 로 변환된다.
              console.log(this);  // global Object
          }
        
          // AO 에 포함된 내부 함수를 호출한다.
          B(); // AO.B();
            
          // 초기화된 this 값을 반환한다.
          return this;
      }
        
      // this 는 undefined 로 초기화되며, undefined 는 this 로 평가될 수 없으므로, 암묵적으로 global Object 로 변환된다.
      console.log(A()); // global Object
        
      // this 는 생성된 인스턴스로 초기화된다.
      console.log(new A()); // A Object
        
      // this 는 null 로 초기화되며, null 은 this 로 평가될 수 없으므로, 암묵적으로 global Object 로 변환된다.
      console.log(A.call(null)); // global Object
        
      // this 는 전달된 {x: 1} 객체로 초기화된다.
      console.log(A.call({x: 1})); // Object {x: 1}
        
      // this 는 전달된 {x: 2} 객체로 초기화된다.
      console.log(A.apply({x: 2})); // Object {x: 2}
        
      // this 는 전달된 {x: 2} 객체로 초기화된다.
      console.log(A.bind({x: 3})()); // Object {x: 3}
      ```
      
    • 바인딩된 익명 함수 내부에서의 this

      ```javascript
      // 버튼 객체를 생성한다.
      var btnElem = document.querySelector('#btn1');
        
      // 생성된 버튼 객체에 click 이벤트를 바인딩한다.
      btnElem.addEventListener('click', function(){
        
          // 이 경우 this 값은 target element 인 btnElem 객체를 가리킨다.
          console.log(this); // btnElem object        
      });
      ```
      
    • bind 함수를 통해 (바인딩된)함수 내부 this 값을 전역 스코프의 this 값으로 초기화 시킬 수 있다.

      ```javascript
      // 버튼 객체를 생성한다.
      var btnElem = document.querySelector('#btn1');
        
      // 생성된 버튼 객체에 click 이벤트를 바인딩한다.
      btnElem.addEventListener('click', function(){
        
          // 이 경우 this 값은 bind 함수를 통해 초기화된 this 값을 가리킨다.
          console.log(this); // global object
      }.bind(this));
      ```      
      
    • this 값 초기화 테스트 in Strict Mode

      • Strict Mode 에서는 this 값이 null, 또는 undefined 인 경우, 암묵적으로 global Object 로 변환되지 않는다.

          // A 함수 객체를 선언한다.
          function A() {
        
              // Strict Mode 선언
              'use strict';
        
              function B() {
                  // this 는 undefined 로 초기화된다.
                  console.log(this);  // undefined
              }
        
              // AO 에 포함된 내부 함수를 호출한다.
              B(); // AO.B();
        
              // 초기화된 this 값을 반환한다.
              return this;
          }
        
          // this 는 undefined 로 초기화된다.
          console.log(A()); // undefined
        
          // this 는 global object 로 초기화된다.
          console.log(this.A());
        
          // this 는 생성된 인스턴스로 초기화된다.
          console.log(new A()); // A Object
        
          // this 는 null 로 초기화된다.
          console.log(A.call(null)); // global Object
        
          // this 는 전달된 {x: 1} 객체로 초기화된다.
          console.log(A.call({x: 1})); // Object {x: 1}
        
          // this 는 전달된 {x: 2} 객체로 초기화된다.
          console.log(A.apply({x: 2})); // Object {x: 2}
        
          // this 는 전달된 {x: 2} 객체로 초기화된다.
          console.log(A.bind({x: 3})()); // Object {x: 3}
        
    • this 값 초기화 테스트 in Object

      • 객체 메서드에서의 this 는 해당 메서드를 내부 프로퍼티로 소유한 객체를 가리킨다.

          var A = {
              x: function(){
        
                  var B = function(){
                      // this 는 undefined 로 초기화되며, undefined 는 this 로 평가될 수 없으므로, 암묵적으로 global Object 로 변환된다.
                      console.log(this); // global Object
                  }
        
                  // AO 에 포함된 내부 함수를 호출한다.
                  B(); // AO.B();
        
                  // 초기화된 this 값을 반환한다.
                  return this;
              }
          };
        
          // 이 경우 this 는 해당 함수를 내부 프로퍼티로 소유한 객체를 가리킨다.
          console.log(A.x()); // A Object
        

    3. ES6 Arrow Function & this

    • Arrow Function 은 자신만의 this, arguments, super, new.target 이 할당되지 않는다.

    • Arrow Function 의 this 값은 함수가 위치한 지점을 둘러싼, 전역/함수 스코프this 값을 가리키며, 바인딩된 후 변하지 않는다.

            
        // global execution context
            
        // Arrow Function 을 할당한다.
        var A = () => {
            
            // A function execution context
            
            var B = () => {
                
                // B function execution context
                    
                // 이 경우 this 는 (B)함수를 둘러싼, (A)함수 스코프의 this(global Object) 값으로 초기화된다.
                console.log(this);
            }
            
            B();
            
            // 초기화된 this 값을 반환한다.
            return this;
        };
            
        // this 는 global object 로 초기화된 후 변하지 않는다. 
        console.log(A()); // global Object
            
        // this 는 global object 로 초기화된 후 변하지 않는다.
        console.log(this.A()); // global Object
            
        // new 연산자를 통해 새로운 인스턴스 생성 시 에러가 발생한다.
        try {
            console.log(new A());
        }
        catch(e){
            // Uncaught TypeError: () => this is not a constructor
            console.log(e.message);
        }
            
        // this 는 global object 로 초기화된 후 변하지 않는다.
        console.log(A.call(null)); // global Object
            
        // this 는 global object 로 초기화된 후 변하지 않는다.
        console.log(A.call({x: 1})); // global Object
            
        // this 는 global object 로 초기화된 후 변하지 않는다.
        console.log(A.apply({x: 2})); // global Object
            
        // this 는 global object 로 초기화된 후 변하지 않는다.
        console.log(A.bind({x: 3})()); // global Object
            
      
    • 바인딩된 익명 (Arrow)함수 내부에서의 this

        // 버튼 객체를 생성한다.
        var btnElem = document.querySelector('#btn1');
            
        // 생성된 버튼 객체에 click 이벤트를 바인딩한다.
        btnElem.addEventListener('click', () => {
            
            // 이 경우 arrow function 의 this 값은 해당 함수를 둘러싼 전역 스코프의 this 값으로 초기화된다.
            console.log(this); // global Object
                
            // 버튼 객체를 통해 명시적으로 접근한다.
            console.log(btnElem);
        });
      
    • 함수 객체 내부에서의 Arrow Functionthis

        function A(){
            
            // arrow function
            var B = () => {
                // 이 경우 this 는 (B)함수를 둘러싼, (A)함수 스코프의 this(global Object) 값으로 초기화된다.
                console.log(this); // global Object
            };
            
            B();
            
            // 초기화된 this 값을 반환한다.
            return this;
            
        }
            
        // this 는 global Object 로 초기화된다.
        A();
      
    • 생성자 함수 객체 내부에서의 Arrow Functionthis 값(Arrow Functionthis 값을 동적 바인딩하기위한 방법)

        function A(){
            
            // arrow function
            var B = () => {
                // 이 경우 this 는 (B)함수를 둘러싼, (A)함수 스코프의 this(A Object) 값으로 초기화된다.
                console.log(this); // A Object
            };
            
            B();
            
            // 초기화된 this 값을 반환한다.
            return this;
            
        }
            
        // this 는 생성된 인스턴스로 초기화된다.
        console.log(new A()); // A Object
      
    • 객체 메서드에서의 this 는 해당 메서드를 둘러싼, 전역 스코프의 this 값으로 초기화된다.

        var A = {
            normalMethod: function(){
                return this; // A object
            },
            arrowMethod: () => {
                return this; // global object
            }
        };
            
        // 이 경우 this 는 해당 함수를 내부 프로퍼티로 소유한 객체를 가리킨다.
        console.log(A.normalMethod()); // A Object
            
        // 이 경우 this 는 (arrowMethod)함수를 둘러싼, 전역 스코프의 this(global Object) 값으로 초기화된다.
        console.log(A.arrowMethod()); // global Object
      
    • Arrow Function 내부에서의 this 값 변경

        var A = {
            arrowMethod: () => {
            
                var bindFn = function(){
                    console.log(this); // A object
                }.bind(A)();
            
                return this;
            }
        };
            
        console.log(A.arrowMethod()); // global Object
      
    • 그 밖의 테스트

            
        // 객체를 반환하기 위해서는 괄호 연산자 또는 return 문을 사용해야한다.
        {
            let a = () => {x: 1 };
            
            console.log(a()); // undefined
        }
            
        {
            let a = () => ({x: 1});
            
            console.log(a()); // {x: 1} object
        }
            
        {
            let a = () => { return {x: 1}; };
            
            console.log(a()); // {x: 1} object
        }
            
        // IIFE(즉시 실행 함수) 는 아래와 같이 표현될수 있다.
        console.log((() => 1)()); // 1
      

    관련 URL

    Read more