본문 바로가기

프로그래밍/javascript

javascript의 this 그리고 [call,bind,apply] 함수

자바스크립트의 this는 python의 self 나 c#의 this와는 조금 다른 개념으로 사용된다.

보통의 프로그래밍 언어에서 this는 class에서 현재 인스턴스를 지칭하는데 사용되는것에 반해,

javascript에 this의 값은 함수를 호출한 방법 및 환경에 따라 결정된다. 

 *실행중에는 할당으로 설정할 수 없고 함수를 호출할 때 마다 다를 수 있다. ???

function f1() {
  return this;
}

// 브라우저
f1() === window; // true

// Node.js
f1() === global; // true

기본적으로 this = global 즉, 아래와 같다.

// 변수를 선언하고 변수에 프로퍼티로 전역 window를 할당
var a = 'Global';

function whatsThis() {
  return this.a;  // 함수 호출 방식에 따라 값이 달라짐
}

whatsThis();          // this는 'Global'. 함수 내에서 설정되지 않았으므로 global/window 객체로 초기값을 설정한다.

 

this를 한 문맥에서 다른 문맥으로 넘기려면

// call 또는 apply의 첫 번째 인자로 객체가 전달될 수 있으며 this가 그 객체에 묶임
var obj = {a: 'Custom'};

// 변수를 선언하고 변수에 프로퍼티로 전역 window를 할당
var a = 'Global';

function whatsThis() {
  return this.a;  // 함수 호출 방식에 따라 값이 달라짐
}

whatsThis();          // this는 'Global'. 함수 내에서 설정되지 않았으므로 global/window 객체로 초기값을 설정한다.
whatsThis.call(obj);  // this는 'Custom'. 함수 내에서 obj로 설정한다.
whatsThis.apply(obj); // this는 'Custom'. 함수 내에서 obj로 설정한다.

이를 잘 활용하면

apply() 메서드는 주어진 this 값과 배열 (또는 유사 배열 객체) 로 제공되는 arguments 로 함수를 호출합니다. 

apply 함수의 첫 번째 인자는 this,이고 두번 째 인자는 배열 입니다.

 

예시 1) 2차원 배열을 1차원으로 만들기 위해 사용한 apply함수 
const concatAll = (array) => {
    let results = [];
    for(const value of array){
        results.push.apply(results, value);
        // 위 부분은 value가 [1,2]라고 했을 때,
        // results.push(1,2) 형태와 같다 
    }
    return results;
}

const variable = [[1,2],[3,4],[5],[6],[7]]

console.log(concatAll(variable))
// -> [1,2,3,4,5,6,7]

 

즉, 배열로 들어온 두번 째 인자를 배열이 아닌 값의 나열(?) 로 바꿔서 적용 해 준다. ex) [1,2,3] => (1,2,3)

 

예시 2) Math.max함수는 배열을 인자로 받지 않지만, 아래와 같이 apply 함수를 이용하면 활용 할 수 있다.

const nums = [1,2,3,4,8,5,6]
console.log(Math.max.apply(null,nums))

위 코드의 실행 결과는 아래 코드와 같다. 직접 실행 해 보시길!

console.log(Math.max(1,2,3,4,8,5,6))

마지막으로, bind 함수는 

function f() {
  return this.a;
}

var g = f.bind({a: 'azerty'});
console.log(g()); // azerty

var h = g.bind({a: 'yoo'}); // bind는 한 번만 동작함!
console.log(h()); // azerty

var o = {a: 37, f: f, g: g, h: h};
console.log(o.a, o.f(), o.g(), o.h()); // 37, 37, azerty, azerty

apply와 call이 함수에 this를 적용 하는 것이라면, bind는 object의 this를 바꿔주는 식으로 적용된다.

참고. 

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Function/apply