JavaScript thisの定理

27893 ワード

JAvascript thisバインド

자바스크립트의 this는 현재 실행 문맥이다. 여기서 현재 실행 문맥이라는 건 무엇을 뜻할까? 바로 호출자를 뜻한다.
호출자는 크게 세 가지로 나뉘어진다. 첫 번째는 객체의 메소드, 두 번째는 함수, 그리고 마지막으로 생성자 함수이다. 
만약 this가 나온다면 이 세 가지 경우 중 하나이니 누가 호출했는지 보고 this가 어떤 의미를 가지는지를 따져보면 된다. 
이를 함수 호출 패턴이라고 하며, 자바스크립트의 this 는 함수 호출 패턴에 따라 this 가 어떤 객체의 this 가 될 지 정해진다. 
이를 this 바인딩이라고 한다.
바인딩(biding)의 사전적 의미는 묶이다인데, 누가 호출했는지에 따라 this가 호출자에게 묶인다는 의미로 이해하면 그나마 이해하기 쉬워진다.

このバインディングの呼び出しモード

  • オブジェクトメソッドが呼び出されたときのこのバインド
    呼び出し
  • 自体のオブジェクトにバインドされます.
  •       var obj = {
            sayName: function() {
              console.log(this.name);
            }
          };
    
          var kim = obj;
          kim.name = "kim";
          kim.sayName(); // "kim"
    
          var lee = obj;
          lee.name = "lee";
          lee.sayName(); // "lee"
  • 関数が呼び出されたときのこのバインド
  • グローバルオブジェクト(ウィンドウ)にバインドします.
  •     var val = "Hello";
    
        var func = function() {
          console.log(this.val);
        };
        func(); // "Hello"
        console.log(this.val); // "Hello"
        console.log(window.val); //  "Hello"
        console.log(this === window); // true
       하지만 함수 호출에서의 this 바인딩은 내부 함수를 호출할 때도 그대로 적용이 된다. 
       아래 예제를 보면, 결과가 2,3,4 로 나와야 할 것 같지만 그렇게 나오지 않는다. 
       왜냐면 자바스크립트가 내부 함수 호출 패턴을 정해놓지 않았기 때문에, 내부 함수도 함수 취급을 받아 이러한 결과가 나온 것이다.
       따라서 함수 호출 패턴 패턴 규칙에 따라 내부 함수의 this 는 전역 객체(window)에 바인딩된다.
        // 전역 변수 value 정의
        var value = 100;
    
        // myObject 객체 생성
        var myObject = {
          value: 1,
          func1: function() {
            this.value += 1;
            console.log("func1() called. this.value : " + this.value);
    
            // func2() 내부 함수
            func2 = function() {
              this.value += 1;
              console.log("func2() called. this.value : " + this.value);
    
              // func3() 내부 함수
              func3 = function() {
                this.value += 1;
                console.log("func3() called. this.value : " + this.value);
              };
    
              func3(); // func3() 내부 함수 호출
            };
            func2(); // func2() 내부 함수 호출
          }
        };
        myObject.func1(); // func1() 메소드 호출
       위와 같은 상황을 피하려면, 부모 함수의 this 를 내부 함수가 접근 가능한 다른 변수에다 저장해야 한다. 
       보통 this 값을 저장하는 변수의 이름을 that 이라고 짓는다.
        // 내부 함수 this 바인딩
        var value = 100;
    
        var myObject = {
          value: 1,
          func1: function() {
            var that = this; // 부모 함수의 this를 that으로 저장
    
            this.value += 1;
            console.log("func1() called. this.value : " + this.value);
    
            func2 = function() {
              that.value += 1;
              console.log("func2() called. this.value : " + that.value);
    
              func3 = function() {
                that.value += 1;
                console.log("func3() called. this.value : " + that.value);
              };
              func3();
            };
            func2();
          }
        };
    
        myObject.func1(); // func1 메소드 호출
  • コンストラクション関数を呼び出すときのこのバインド
  • newで作成されたコンストラクション関数のオブジェクトにバインドされます.
  •     var Person = function(name) {
          this.name = name;
        };
    
        var kim = new Person("kim");
        console.log(kim.name); //kim
    
        var lee = new Person("lee");
        console.log(lee.name); //lee

    Call、Apply、Bind関数の場合

    3가지 방법은 this를 바인딩 하기 위한 방법.
    
    Call() : this를 바인딩하면서 함수를 호출하는 것, 두 번째 인자를 하나씩 넘기는 것
    Apply() : this를 바인딩하면서 함수를 호출하는 것, 두 번째 인자가 배열
    bind() : 함수를 호출하는 것이 아닌 this가 바인딩된 새로운 함수를 리턴함.

    矢印関数

  • 宣言
  • // 매개변수 지정 방법
          () => { ... } // 매개변수가 없을 경우
           x => { ... } // 매개변수가 한 개인 경우, 소괄호를 생략할 수 있다.
      (x, y) => { ... } // 매개변수가 여러 개인 경우, 소괄호를 생략할 수 없다.
    
      // 함수 몸체 지정 방법
      x => { return x * x }  // single line block
      x => x * x             // 함수 몸체가 한줄의 구문이라면 중괄호를 생략할 수 있으며 암묵적으로 return된다. 위 표현과 동일하다.
    
      () => { return { a: 1 }; }
      () => ({ a: 1 })  // 위 표현과 동일하다. 객체 반환시 소괄호를 사용한다.
    
      () => {           // multi line block.
        const x = 10;
        return x * x;
      };
    呼び出し
  • 関数
  •   화살표 함수는 익명 함수로만 사용할 수 있다. 따라서 화살표 함수를 호출하기 위해서는 함수 표현식을 사용한다.
      
        // ES6
        const pow = x => x * x;
        console.log(pow(10)); // 100
      
      또는 콜백 함수로 사용할 수 있다. 이 경우 일반적인 함수 표현식보다 표현이 간결하다.
      
        // ES6
        const arr = [1, 2, 3];
        const pow = arr.map(x => x * x);
    
        console.log(pow); // [ 1, 4, 9 ]
  • 矢印関数のthisは常に上位のthisを指します.これをメキシコと言います.
  •     function Prefixer(prefix) {
          this.prefix = prefix;
        }
    
        Prefixer.prototype.prefixArray = function (arr) {
          // this는 상위 스코프인 prefixArray 메소드 내의 this를 가리킨다.
          return arr.map(x => `${this.prefix}  ${x}`);
        };
    
        const pre = new Prefixer('Hi');
        console.log(pre.prefixArray(['Lee', 'Kim']));
  • 矢印関数はcall、apply、bindメソッドを使用して変更できません.
  •     window.x = 1;
        const normal = function () { return this.x; };
        const arrow = () => this.x;
    
        console.log(normal.call({ x: 10 })); // 10
        console.log(arrow.call({ x: 10 }));  // 1

    リファレンス

  • https://poiemaweb.com/es6-arrow-function
  • https://velog.io/@cjh 951114/よくある質問-02--javascript-thisバー
  • https://www.zerocho.com/category/JavaScript/post/57433645a48729787807c3fd
  • https://seonghui.github.io/blog/2018/10/12/js-this/