JavaScript/node.js

this call() apply() bind()

짱닭 2020. 10. 20. 19:55
반응형

this

패턴바인딩되는 객체 (브라우저)바인딩되는 객체 (node.js)
Globalwindow (strict mode - undefined)module.exports
Function 호출window (strict mode - undefined)global

화살표함수의 this

    const foo = () => {
      return this
    }


    foo() === module.exports   //true

메서드 안에서 this를 호출하면 global이 바인딩되는 것이 맞지만,
화살표 함수 내에서 this를 호출하면 메서드 내부에서 호출한 것이 아닌
해당 함수가 선언된 위치를 기준으로 this 가 바인딩 되게 된다.
(*좋은 설명 있으면 추가할 것.)

call()

call은 항상 함수를 "실행"한다.

첫 번째 인자가 항상 this 값이 된다. this값을 명시하고 싶을 때 사용.

    function foo() {
      return this;
    }

    const context1 = { msg: 'welcome everyone' }
    const context2 = { msg: 'good bye' }


    foo.call(context1) === context1   //true
    foo.call(context2).msg === 'good bye'  //true

두번째 인자 이후로는 파라미터로 전달된다.

    function printProfile(name, age, ...args) {
      return `${this.type} ${name} 나이:${age}${args.length === 0 ? '' : ' ' + this.feature + ':' + args.join(',')}`
    }

    const developer = { type: '개발자', feature: '언어' }
    const artist = { type: '아티스트', feature: '노래' }



    printProfile.call(developer, '김코딩', 30) === '개발자 김코딩 나이:30'  //true

apply()

첫 번째 인자가 항상 this 값이 된다. this값을 명시하고 싶을 때 사용.

두번째 인자는 배열이다.

    function printProfile(name, age, ...args) {
      return `${this.type} ${name} 나이:${age}${args.length === 0 ? '' : ' ' + this.feature + ':' + args.join(',')}`
    }

    const developer = { type: '개발자', feature: '언어' }
    const artist = { type: '아티스트', feature: '노래' }



    printProfile.apply(developer, ['김코딩', 30]) === '개발자 김코딩 나이:30'  //true

this값이 필요하지 않을 때는 null을 인자로 전달해서
아무 값도 전달해 주지 않아도 된다.

let arr = [ 1, 2, 5, 8, 10 ]


Math.max.apply(null, arr) === 10   //true

prototype의 기능을 빌려쓸 수 있다.

let arr1 = ['code', 'states']
let arr2 = ['one', 'two']



Array.prototype.concat.call(arr1, arr2) === ['code', 'states', 'one', 'two'] )
Array.prototype.concat.apply(arr1, [arr2]) === ['code', 'states', 'one', 'two'])

유사배열을 다루기 용이하다.

const nodeList = {
      length: 3,
      0: 'div#target',
      1: 'li',
      2: 'span#new'
    };



    Array.prototype.slice.apply(nodeList, [0, 1]) === ['div#target']   //true
    Array.prototype.map.call(nodeList, node => node.split('#')[0]) === ['div', 'li', 'span']  //true

bind()

call()과 달리 함수를 실행하지 않고 this 값만 할당한다.

this 값을 임의로 명시해주기 위해 사용한다.

인자 순서는 call()과 동일.

new 키워드

    let this_value_in_constructor;

    function Car(name, brand, color) {
      this.name = name;
      this.brand = brand;
      this.color = color;

      this_value_in_constructor = this;
    }

위와 같은 코드가 있다고 할 때,

const mycar = new Car('458', 'ferrari', 'red');

this_value_in_constructor === mycar;   //true

위처럼 new 키워드로 생성자 함수를 호출하면 this의 값이 new 키워드가 호출되어 할당된 객체가 된다.

하지만 여기서 new 키워드를 생략하고 Car 함수를 호출한다면,

const secondCar = Car('spark', 'chevrolet', 'violet');

typeof secondCar === undefined;  //true
this_value_in_constructor === global;  //true

new 키워드가 없어도 어쨋든 함수는 실행되기 때문에
this 의 값은 메서드 내에서 this를 호출한 것 처럼 global이 된다.

하지만,
secondCar에는 생성자 함수가 호출되지 않았기 때문에 아무값도 할당되지 않는다.

반응형