자바스크립트의 함수는 호출될 때, 매개변수로 전달되는 인자값 이외에, arguments 객체와
this
를 암묵적으로 전달 받는다.해당 함수 호출 방식에 의해
this
에 바인딩 되는 객체가 달라진다.
var foo = function () {
console.dir(this);
};
// 1. 함수 호출
foo(); // window
// window.foo();
// 2. 메소드 호출
var obj = { foo: foo };
obj.foo(); // obj
// 3. 생성자 함수 호출
var instance = new foo(); // instance
// 4. apply/call/bind 호출
var bar = { name: 'bar' };
foo.call(bar); // bar
foo.apply(bar); // bar
foo.bind(bar)(); // bar
전역객체는 일반적으로 Browser-side에서는 window
, Server-side(Node.js)에서는 global
객체를 의미한다.
전역객체는 전역 스코프를 갖는 전역변수를 property로 소유한다.
기본적으로 this
는 전역객체에 바인딩 되며, 내부함수는 일반 함수, 메소드, 콜백함수 어디에서 선언되었든 관계없이 전역객체를 바인딩한다.
// in browser console
this === window // true
// in Terminal
node
this === global // true
함수가 객체의 property 값이면 메소드로써 호출 되어, 해당 메소드를 소유한 객체에 바인딩 된다.
var obj1 = {
name: 'Lee',
sayName: function() {
console.log(this.name);
}
}
var obj2 = {
name: 'Kim'
}
obj2.sayName = obj1.sayName;
obj1.sayName(); // Lee
obj2.sayName(); // Kim
기존 함수에 new 연산자를 붙여서 호출하면 해당 함수는 생성자 함수로 동작한다.
new 연산자와 함께 생성자 함수를 호출하면 this바인딩이 메소드나 함수 호출 때와는 다르게 동작한다.
function Person(name) {
// 생성자 함수 코드 실행 전 -------- 1
this.name = name; // --------- 2
// 생성된 함수 반환 -------------- 3
}
var me = new Person('Lee');
console.log(me.name);
apply() 메소드는 this를 특정 객체에 바인딩할 뿐 본질적인 기능은 함수 호출이다.
var value = 1;
var obj = {
value: 100,
foo: function() {
console.log("foo's this: ", this); // obj
console.log("foo's this.value: ", this.value); // 100
function bar(a, b) {
console.log("bar's this: ", this); // obj
console.log("bar's this.value: ", this.value); // 100
console.log("bar's arguments: ", arguments);
}
bar.apply(obj, [1, 2]);
bar.call(obj, 1, 2);
bar.bind(obj)(1, 2);
}
};
obj.foo();
apply()와 call() 메소드는 콜백 함수의 this를 위해서 사용되기도 한다.
function Person(name) {
this.name = name;
}
Person.prototype.doSomething = function(callback) {
if(typeof callback == 'function') {
// --------- 1: this === Person
callback();
}
};
function foo() {
console.log(this.name); // --------- 2: this === window
}
var p = new Person('Lee');
p.doSomething(foo); // undefined
function Person(name) {
this.name = name;
}
Person.prototype.doSomething = function (callback) {
if (typeof callback == 'function') {
callback.call(this);
}
};
function foo() {
console.log(this.name);
}
var p = new Person('Lee');
p.doSomething(foo); // 'Lee'
Function.prototype.bind는 함수에 인자로 전달한 this가 바인딩된 새로운 함수를 리턴한다. 즉, Function.prototype.bind는 Function.prototype.apply, Function.prototype.call 메소드와 같이 함수를 실행하지 않기 때문에 명시적으로 함수를 호출할 필요가 있다.