자바스크립트에서는 함수를 호출하면 실행 컨텍스트가 생성되고 그 안에 VariableEnvironment, LexicalEnvironment, ThisBinding 정보가 저장된다. 즉, 함수를 호출할 때 this가 결정되는 것이다.
this에는 호출한 주체에 대한 정보가 담기기 때문에 함수를 호출하는 방식에 따라 바인딩되는 객체가 달라진다. 지정된 객체가 없으면 기본적으로 전역객체를 바라보게 된다.
함수와 메소드를 구분하는 유일한 차이는 독립성이다.
함수는 그 자체로 독립적인 기능을 수행하지만, 메소드는 자신을 호출한 대상 객체에 관한 동작을 수행한다.
흔히 객체의 프로퍼티에 할당된 함수를 메소드라고 부르지만 완전히 맞는 말은 아니다. 객체의 프로퍼티에 할당된 함수여도 메소드로 호출해야만 메소드로 동작하고, 그렇지 않으면 함수로 동작한다.
메소드로 호출하려면 함수명 앞에 객체를 명시해주면 된다. 점 표기법과 대괄호 표기법을 이용하는 두 가지 방법이 있다.
var obj = {
method: function() { ... }
}
obj.method(); //점 표기법
obj['method'](); //대괄호 표기법
var func = function(x) {
console.log(this, x);
}
func(1); // window { ... } 1
함수를 호출하는 것은 호출 주체를 명시하지 않고 개발자가 직접 코드에 관여하여 호출한 것이므로 this가 지정되지 않는다. 따라서 전역객체를 가리킨다.
var func = function(x) {
console.log(this, x);
}
var obj = {
method: func
}
obj.method(2); // { method: f } 2
호출 주체인 객체를 가리킨다. 위 예시에서는 메소드의 호출 주체가 obj이므로 this는 obj를 가리키게 된다.
콜백함수란?
다른 코드의 인자로 넘겨줌으로써 함수의 제어권을 다른 함수에게 넘기는 함수
제어권을 넘겨받은 함수의 내부 로직에 따라 실행된다.
콜백함수도 함수이므로 기본적으로 전역객체를 가리키지만, 제어권을 받은 함수에서 콜백함수에 this를 지정해주면 그 대상을 참조한다.
addEventListener 메소드의 경우, 콜백함수를 호출할 때 자신의 this를 상속하도록 정의되어 있다.
콜백함수를 인자로 받는 메소드 중 일부는 추가로 this로 지정할 객체를 인자로 지정할 수 있으며, 주로 배열 메소드가 포함되는 경우가 많다.
생성자 함수란?
어떤 공통된 성질을 가진 객체들을 생성하는 함수
함수 앞에 new 명령어를 붙여 호출하면 생성자 함수로 동작하게 된다.
var Cat = function(name, age) {
this.name = name;
this.age = age;
}
var choco = new Cat('초코', 1); // Cat { name='초코', age=1 }
var nabi = new Cat('나비', 2); // Cat { name='나비', age=2 }
생성자 함수로 호출되면 내부의 this는 생성되는 객체를 가리키게 된다.
func.call(thisArg[, arg1[, arg2[, ...]]])
메소드의 호출 주체인 함수를 즉시 실행시킨다.
첫번째 인자로 this에 바인딩할 객체를 넘기고, 이후의 인자들을 호출할 함수의 매개변수로 넘긴다.
func.apply(thisArg, [argsArray])
call 메소드와 동일한 기능을 한다.
단, 매개변수를 넘길 때 배열로 묶어서 넘긴다는 차이가 있다.
func.bind(thisArg[, arg1[, arg2[, ...]]])
넘겨받은 this와 인자들을 바탕으로 새로운 함수를 반환한다.
call, apply와 달리 함수를 실행시키지 않기 때문에 명시적으로 함수를 호출해줘야 한다.
상위 스코프의 this를 변수에 담아놓고 내부의 함수에서 그 변수를 활용한다.
ES6에서 새롭게 도입된 함수로, 실행 컨텍스트를 생성할 때 this를 바인딩하는 과정이 제외되었다. 따라서 화살표 함수 내부에는 this가 아예 없기 때문에, 접근하고자 하면 스코프 체인 상 가장 가까운 this를 참조하게 된다.