this
를 왜? 더 깔끔한 API, 그리고 재사용하기 쉽다.
function identify() {
return this.name.toUpperCase();
}
function speak() {
var greeting = "Hello, I'm " + identify.call( this );
console.log( greeting );
}
var me = {
name: "Kyle"
};
var you = {
name: "Reader"
};
identify.call( me ); // KYLE
identify.call( you ); // READER
speak.call( me ); // Hello, I'm KYLE
speak.call( you ); // Hello, I'm READER
//the same
function identify(context) {
return context.name.toUpperCase();
}
function speak(context) {
var greeting = "Hello, I'm " + identify( context );
console.log( greeting );
}
identify( you ); // READER
speak( me ); // Hello, I'm KYLE
function 자체를 가리키지 않는다.
function foo(num) {
console.log( "foo: " + num );
// keep track of how many times `foo` is called
this.count++;//global variable and valus is NaN
}
foo.count = 0;//OBJECT foo' property.
var i;
for (i=0; i<10; i++) {
if (i > 5) {
foo( i );
}
}
// foo: 6
// foo: 7
// foo: 8
// foo: 9
// how many times was `foo` called?
console.log( foo.count ); // 0 -- WTF?
함수 객체를 가리키는 식별자를 이용해서 접근은 가능하다.
function foo() {
foo.count = 4; // `foo` refers to itself
}
setTimeout( function(){
// anonymous function (no name), cannot
// refer to itself
}, 10 );
.call()
을 이용하여 this가 함수 객체를 가리키도록 할 수 있다.
function foo(num) {
console.log( "foo: " + num );
// keep track of how many times `foo` is called
// Note: `this` IS actually `foo` now, based on
// how `foo` is called (see below)
this.count++;
}
foo.count = 0;
var i;
for (i=0; i<10; i++) {
if (i > 5) {
// using `call(..)`, we ensure the `this`
// points at the function object (`foo`) itself
foo.call( foo, i );
}
}
// foo: 6
// foo: 7
// foo: 8
// foo: 9
// how many times was `foo` called?
console.log( foo.count ); // 4
스코프를 가리키는 것도 아니다. 애초에 스코프를 엔진 동작의 부분이기 때문에.
function foo() {
var a = 2;
this.bar();//this. delete
}
function bar() {
console.log( this.a );//this참조로 lexical scope를 조사할 수 없다.
}
foo(); //undefined
this
는 런타임 binding으로 함수 invocation의 조건에 기반을 둔다. 함수가 어디에서 선언되었는지와는 일절 상관이 없고 어떤 방식으로 called 했는지가 중요하다.
함수 invoked 시, 실행 컨텍스트라고 알려진 activation record이 생성되어 함수 call장소(the call-stack), 함수 invoked 방식, parameter 등에 대한 정보를 담고 있다. 이 record의 하나의 속성이 함수 실행 동안 사용되는 this 참조다.
정리를 살짝 하자면, this
는 함수 invoked 시 만들어지는 binding으로 무엇을 참조하는지는 전적으로 call-site에 의해 결정된다.