ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바스크립트 Chapter 15 this, call, apply and bind
    Computer Science/JavaScript 2019.05.08 20:03

     

    자바스크립트 핵심 컨셉 33가지

     

    Chapter 15 this, call, apply and bind

     

    이번 장에서는 this, call, apply 그리고 bind에 대하여 알아보자.

     

    함수가 생성되면, this라는 키워드가 만들어져 함수가 작동하는

     

    객체에 연결이 된다.

     

    this 키워드의 값은 함수 자체와는 아무런 관련이 없다.

     

    this 값은 함수의 호출 방식이 결정한다.

     

    const myFunction = function() {
      console.log(this)
    }
    
    myFunction();

     

    기본적으로 this는 window-object이다.

     

    const myObject = {
      myMethod: function() {
        console.log(this)
      }
    }

     

    여기서 this는 무엇일까?

     

    알 수 없다.

     

    왜냐하면 this 값은 함수 자체와 아무런 관련이 없기 때문이다.

     

    함수가 호출되는 방식이 this 값을 결정한다.

     

    const myMethod = function() {
      console.log(this);
    };
    
    const myObject = {
      myMethod: myMethod
    };

     

    myObject에서 myMethod 속성(property)은 myMethod 함수를 가리킨다.

     

    myMethod 함수가 전역 범위에서 호출되면,

     

    this는 window-object를 참조한다.

     

    myObject의 메서드로 호출되면, this는 myObject를 참조한다.

     

    myObject.myMethod() // this === myObject
    myMethod() // this === window

     

    이것을 implicit binding(암시적 바인딩)이라고 한다.

     

    Explicit binding은 명시적으로 함수에 바인딩할 때를 의미한다.

     

    Function.prototype.call() or Function.prototype.apply로 수행한다.

     

    const myMethod = function() {
      console.log(this)
    }
    
    const myObject = {
      myMethod: myMethod
    }
    
    myMethod() // this === window
    myMethod.call(myObject, args1, args2, ...) // this === myObject 함수에 전달될 인수 리스트를 받음.
    myMethod.apply(myObject, [array of args]) // this === myObject 함수에 전달될 인수들의 단일 배열을 받음.

     

    그렇다면, Implicit와 Explicit 둘 중 어떤 것이 더 우선할까?

     

    const myMethod = function() {
      console.log(this)
    }
    
    const obj1 = {
      a:2,
      myMethod: myMethod
    }
    
    const obj2 = {
      a:3,
      myMethod: myMethod
    }
    
    obj1.myMethod(); // 2
    obj2.myMethod(); // 3
    
    obj1.myMethod.call(obj2); // 3
    obj2.myMethod.call(obj1); // 2

     

    Explicit 바인딩이 Implicit 바인딩 보다 우선시된다.

     

    즉 암시적 바인딩을 확인하기 전에

     

    명시적 바인딩이 적용되는지 확인해야 한다.

     

    Hard binding은 Function.Prototype.bind()을 이용한다.

     

    bind()는 this 키워드를 주어진 값으로 설정하고,

     

    원래 함수를 호출하도록 새 함수를 반환한다.

     

    즉 bind() 함수는 새로운 바인딩한 함수를 만들고,

     

    바인딩한 함수는 원본 함수 객체를 감싸는 함수이다.

     

    myMethod = myMethod.bind(myObject);
    
    myMethod(); // this === myObject

     

    Hard binding은 Explicit binding보다 우선한다.

     

    let myMethod = function () {
      console.log(this)
    }
    
    const obj1 = {
     a: 2
    }
    
    const obj2 = {
     a: 3
    }
    
    myMethod = myMethod.bind(obj1) // 2
    myMethod.call(obj2) // 2

     

    New binding

     

    함수가 new 키워드와 함께 호출되었을 때 생성된

     

    새로운 인스턴스를 참조한다.

     

    function foo(a) {
    	this.a = a;
    }
    
    const bar = new foo(2)
    console.log(bar.a); // 2

     

    함수가 new로 호출되면 암시적(implicit), 명시적(explicit)

     

    또는 Hard binding에 대해 신경 쓰지 않는다.

     

    function foo(something) {
      this.a = something;
    }
    
    const obj1 = {};
    
    const bar = foo.bind( obj1 );
    bar( 2 );
    console.log( obj1.a ); // 2
    
    const baz = new bar( 3 );
    console.log( obj1.a ); // 2
    console.log( baz.a ); // 3

     

    API calls

     

    Ajax, 이벤트 처리 등을 수행할 때 콜백(callback)을 호출하는데,

     

    이때 주의해야 한다.

     

    myObject = {
      myMethod: function() {
        helperObject.doSomethingCool('superCool', this.onSomethingCoolDone);
        },
        
        onSomethingCollDone: function() {
       
        }
    }

     

    this.onSomethingCoolDone을 콜백(callback)으로 전달하기 때문에

     

    범위(scope)는 호출하는 방법이 아니라 해당 메서드에 대한 참조이다.

     

    위의 문제는 두 가지 해결 방법이 있다.

     

    보통 라이브러리는 다른 매개 변수(parameter)를 제공하므로

     

    반환하려는 범위를 전달할 수 있다.

     

    myObject = {
      myMethod: function () {
        helperObject.doSomethingCool('superCool', this.onSomethingCoolDone, this);
      },
    
      onSomethingCoolDone: function () {
           "this" === myObject
      }
    };

     

    아니면 원하는 범위(scope)로 메서드를 Hard binding 하면 된다.

     

    myObject = {
      myMethod: function () {
        helperObject.doSomethingCool('superCool', this.onSomethingCoolDone.bind(this));
      },
    
      onSomethingCoolDone: function () {
        "this" === myObject
      }
    };

     

    이번 Chapter에서 핵심은

     

    기본적으로 this는 window-object이고

     

    this 값은 함수의 호출 방식이 결정한다는 것이다.

     

    함수의 호출 방식에는 암시적(Implicit) 바인딩과

     

    명시적(Explicit) 바인딩 그리고 Hard binding, New binding이 있다.

     

    명시적(Explicit) 바인딩은 call(), apply()로

     

    Hard binding은 bind()로

     

    New binding은 위의 세 가지 바인딩을 신경 쓰지 않는다.

    댓글 0