본문 바로가기

FrontEnd/javascript

[JS] THIS

반응형

다른언어에서 this 개념을 접했던 분들이라면 자바스크립트의 this도 같을거란 생각으로 접했다 큰 낭패를 보는 경우가 있다
자바스크립트의 this는 다른언어에서와 같이 this가 그 함수 그자체를 가리키지 않는다.
그예를 들어보겠다

function foo(num){
	console.log("foo:" + num);
    this.count++;
}

foo.count = 0;

for(let i=0; i<10;i++){
	if(i > 5){
    	foo(i);
    }
}

//foo:6
//foo:7
//foo:8
//foo:9

console.log(foo.count);		//0 

위결과를 보면 최종 foo.count는 4가 아니고 0을 나타낸다
분명 foo 함수에서 호출될때마다  this.count++;을 하였는데 왜 0일까
즉 this가 자기자신을 가리키지 않는다는것이다.
그러면 foo함수 안에 있는 this.count는 어디에 저장되있을까?
위소스상 foo를 호출하는 부분이  main scope 이면 전역객체에 count 값이 저장 되었을것이다.

자바스크립트의 this는 작성시점이 아닌 런타임 시점에서 바이딩 되며 함수 호출 당시 상황에 따라 컨텍스트가 결정된다
즉 누가 어떻게 함수를 호출하였냐에 따라 this가 결정된다

바인딩


1. 기본 바인딩
가장 평범한 함수 호출인 단독 함수 실행에 관한 규칙으로 this의 기본 규칙이다.

function foo(){
	console.log(this.a);
}
let a = 2;
foo();	//2

위의경우 foo 호출시 기본 바인딩이 적용되어 a= 2는 전역스코프에 변수를 선언하였으므로 전역 객체를 참조한다.
즉 this는 전역 객체를 를 참조하게 된다.
단 strict mode에서는 전역 객체가 기본 바인딩 대상에서 제외된다.
strict mode로 하였을경우는 this는 undefine가 된다.

2. 암시적 바인딩
호출부에 컨텍스트 객체가 있는지 , 객체의 Owning , Containing 여부에따른 호출이다.

function foo(){
	console.log(this.a);
}

let obj = {
	a:2,
    foo:foo
}

obj.foo();	//2

위의경우 호출한 foo() 함수를 obj에서 프로퍼티로 참조하고있다.
즉 호출부는 obj 컨텍스트로 foo()를 참조하므로 obj 객체는 함수 호출 시점에 함수의 레퍼런스를 Owning , Containing 한다고 볼수있다.
함수 레퍼런스에 대한 컨텍스트 객체가 존재할때 암시적 바인딩 규칙에 따르면 바로 이컨텍스트 객체가 함수 호출시 this에 바인딩 된다.

3. 명시적 바인딩
정리중.....


바인딩 우선순위


1. 명시적 바인딩 ,  암시적 바인딩

Function foo(){
    Console.log(this.a)
}

Let obj1 = {
     a:2,
     Foo:foo
}
Let obj2 = {
    A:3
    Foo:foo
}

Obj1.foo();	//2
Obj2.foo();       //3

obj1.foo.call(obj2);   //3
obj2.foo.call(obj1);   //2

위의 결과에서 알수있듯이 명시적 바인딩이 암시적 바인딩 우선한다.

2. new 바인딩 , 암시적 바인딩

function foo(something){
	this.a = something;
}

let obj1 = {
	foo:foo
};

let obj2 = {};

obj1.foo(2);
console.log(obj1.a);		//2

obj1.foo.call(obj2,3);
console.log(obj2.a);		//3

let bar = new obj1.foo(4);
console.log(obj1.a);		//2
console.log(bar.a);			//4

위의 결과에서 알수있듯이 new 바인딩이 암시적 바인딩 우선한다.

3. new 바인딩  명시적 바인딩

function foo(somthing){
	this.a = somthing;
}

let obj1 = {};
let bar = foo.bind(obj1);
bar(2)l
console.log(obj.a);		//2

let baz = new bar(3);
console.log(obj.a);		//2
console.log(baz.a);		//3

위의 결과에서 알수 있듯이 명시적 바인딩이 new 바인딩 우선한다.




참고 문헌 : YOU DON'T KNOW JS (this와 객체 프로토타입, 비동기와 성능)

반응형

'FrontEnd > javascript' 카테고리의 다른 글

const 정리  (0) 2019.09.01