티스토리 뷰

 

4. new 바인딩

 

자바스크립트 함수와 객체의 가장 흔한 오해 중 하나는 new가 생성자 함수 키워드라는 것이다.

자바스크립트에도 new 연산자가 있고 사용 방법은 겉보기에 다른 클래스 지향 언어와 별 차이가 없어 보여서 그 내부 체계 또한 이와 비슷할 거라 쉽게 단정하지만, 사실 자바스크립트에서 new는 의미상 클래스 지향적인 기능과 아무 상관이 없다.

 

자바스크립트 생성자는 앞에 new 연산자가 있을 때 호출되는 일반 함수에 불과하다. 

그냥 대부분의 함수들은 new를 붙여서 호출 할 수 있다.

이것은 정확히 말하면 생성자 함수가 아니라, '함수를 생성하는 호출'이라고 해야 옳을 것이다.

 

함수 앞에 newfmf qnxdu todtjdwk ghcnfdmf gkaus ekdmarhk rkxdms dlfemfdl dlfdjsksek.

1. 새 객체가 툭 만들어진다.

2. 새로 만들어진 객체의 프로토타입이 연결된다.

3. 새로 생성된 객체는 해당 함수 호출 시 this로 바인딩 된다.

4. 이 함수가 자신의 또 다른 객체를 반환하지 않는 한 new와 함께 호출된 함수는 자동으로 새로 생성된 객체를 반환한다.

 

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

var bar = new foo( 2 );
console.log( bar.a ); // 2

 

우선순위

 

이렇게 4개의 규칙에 대해서 알아봤는데, 우선순위는 어떻게 될까?

 

1. new - new로 함수를 호출했는가? 맞으면 새로 생성된 객체가 this다

2. call과 apply로 호출(명시적 바인딩), 이를테면 bind 하드 바인딩 내부에 숨겨진 형태로 호출됐는가? - 맞으면 명시적으로 지정된 객체가 this다

3. 함수를 콘텍스트(암시적 바인딩), 즉 객체를 소유 또는 포함하는 형태로 호출했는가? -> 맞으면 바로 이 콘텍스트 객체가 this다

4. 그 외의 경우에 this는 기본값(엄격모드는 undefined, 비엄격 모드는 전역 객체)으로 세팅된다.

 

바인딩예외

 

1. call, apply, bind 메서드에 첫 번째 인자로 null 또는 undefined를 넘기면 this 바인딩이 무시되고 기본 바인딩 규칙이 적용된다.

하지만 이러한 경우에 그 함수가 내부적으로 this를 참조하면 기본 바인딩이 적용되어 전역 변수를 참조하거나 최악으로는 변경하는 예기치 못한 일이 발생할 수 있다.

2. 따라서 DMZ객체 (빈객체)를 생성해서 넘겨주는게 좋다.

 

간접레퍼런스

의도적이든 아니든 한 가지 더 유의할 점은 간접 레퍼런스가 생성되는 경우로, 함수를 호출하면 무조건 기본 바인딩 규칙이 적용되어 버린다. 간접 레퍼런스는 할당문에서 가장 빈번하게 발생한다.

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

var a = 2;
var o = { a: 3, foo: foo };
var p = { a: 4 };

o.foo(); // 3
(p.foo = o.foo)(); // 2

 

어휘적 this

 

화살표함수는 에두른 스코프(함수ㄷ 또는 전역)를 보고 this를 알아서 바인딩 한다.

function foo() {
	// return an arrow function
	return (a) => {
		// `this` here is lexically adopted from `foo()`
		console.log( this.a );
	};
}

var obj1 = {
	a: 2
};

var obj2 = {
	a: 3
};

var bar = foo.call( obj1 );
bar.call( obj2 ); // 2, not 3!

 

우린 옛날에 화살표 함수 대신 이것도 썼었다.

function foo() {
	var self = this; // lexical capture of `this`
	setTimeout( function(){
		console.log( self.a );
	}, 100 );
}

var obj = {
	a: 2
};

foo.call( obj ); // 2

 

하지만 이것들은 this를 도망치기 위한 꼼수이기 때문에 추천하지는 않는다는 것을 기억해야 할 것이다.

 

참조 - https://github.com/getify/You-Dont-Know-JS

댓글