개발/Java Script

[JS] 자바스크립트에서 call 과 apply 에서의 this

hojak99 2017. 11. 24. 22:23

Underscore.js 의 each() 함수를 분석하다가 optimizeCb() 라는 함수를 each() 함수 안에서 사용하길래 해당 함수를 또 까보니까  apply() call() 이란 함수를 사용하고 있었다. 대충 보니까 비슷한 용도 같은데 달랐다.


function plus(val_1, val_2) {
    return val_1 + val_2;
};

function applyTest(val_1, val_2){
    // return plus.apply(this, arguments);      // 4
    return plus.apply(this, [val_1, val_2]);    // 4
};
function callTest(val_1, val_2){
    // return plus.call(this, arguments);          // [object Arguments]undefined
    // return plus.call(this, [val_1, val_2]);     // 1,3undefined
    return plus.call(this, val_1, val_2);          // 4
};


다음의 코드를 보면 알 수 있듯이 apply() 함수는 arguments, [val_1, val_2](배열) 와 같이 인자로 넣고, call() 함수는 인자를 순서대로 넣고 있다는 차이가 있다.



여기서 나는 의문이 들었다. this 는 뭘까? 란 의문이 들었고, 한 번 테스트를 통해 알아보았다. (<김x준> 형이 알려줘서 이해에 도움이 많이 되었다 ㅎㅎ 땡스기빙데이~)




function Product(name, price) {
    this.name = name;
    this.price = price;
}


var otherObj = {};
otherObj.name = "aa";
otherObj.price = 5;

function Food(name, price) {
    Product.call(otherObj, name, price);
    this.name = "Food";         // 여기서 this 는 Food 를 가리킴
    console.log(otherObj);      // otherObj 의 name 과 price 가 Food 함수의 인자값으로 초기화
    console.log("this(Food) 값 : " + this.name);     // Food 의 name 을 출력(Food 출력)
}

function Toy(name, price) {
    Product.call(this, name, price);
    this.name = "asdasd";       // 여기서 this 는 Toy 를 가리킴
    console.log(this);          // Toy 의 인자로 robot 을 넣어줬지만 this.name 으로 인해 asdasd 로 변경
}

var cheese = new Food('feta', 5);
var fun = new Toy('robot', 40);

// 출력 결과
// Object {name: "feta", price: 5}
// this(Food) 값 : Food
// Toy {name: "asdasd", price: 40}


다음과 같은 코드로 this 가 대체 무슨 역할인지에 대해서 조금 이해가 갈 수 있을 것이다.


우선 Toy 함수에서 Product.call(this, name, price) 란 코드가 있는데 여기서 this 는 무엇을 가리킬까? 바로, Toy 다.


sum.call() 이나 sum.apply() 는 다른 오브젝트에서 sum 이란 함수가 없으면 함수를 빌려쓰기 위해서 사용한다고 생각하면 된다고 한다.  빌려쓸 때 자기자신의 프로퍼티 데이터를 가지고 sum 을 해줘야 하기 때문에 첫번 째 인자로 this 나 다른 오브젝트를 넘겨준다고 한다. 

(출처 : 김x준 형><)



그래서 위의 코드에서도 Toy 함수에서는 call() 할 때 this 를 인자로 넣어주는데 이것은 Toy 를 가리키고, call() 에서의 name 과 price 는 this로 인해 Toy의 name 과 price 를 가리키게 된다. 


그래서 결국 Toy() 함수에서 this 를 출력시키면 new Toy('robot', 40) 의 코드로 인해 name: "robot" 이 출력되는 것이 아니라 "asdasd" 가 출력되게 된다. 



이제 Food() 함수를 보자.

여기선 지금 call(this, name, price) 가 아닌, call(otherObj, name, price) 로 코드를 작성했다. 아까 위에서 말했 듯이 첫 번째 인자에 들어온 객체의 프로퍼티를 가리키게 된다고 했으므로 call(ohterObj, name, price) 에서 name 과 price 는 Food() 함수에 인자로 들어온 name 과 price 가 아니라 otherObj 의 name 과 price 이다. 


그렇기 때문에 otherObj 를 출력하면 Object {name : "feta", price : 5} 가 출력되는 것이다. 



즉, call(this, ~) 과 apply(this, ~) 에서의 this를 제외한 매개변수(위에서 name과 price) 들의 인자값은 첫번째 인자에 들어온 오브젝트가 가리키고 있는 프로퍼티의 값에 초기화 된다.


반응형