본문 바로가기
Javascript

[Javascript] Javascript 바인딩

by parkjp 2017. 8. 31.

 

1. 기본 바인딩

 

 첫 번째 규칙.

가장 평범한 함수 호출인 '단독 함수 실행'에 관한 규칙으로 다른 나머지 규칙에 해당하지 않

을 경우 적용되는 this의 기본 규칙이다.

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

var a = 2;
foo(); // 2

 

 위 예제 var a = 2처럼 전역 스코프에 변수를 선언하면 변수명과 동일한 이름의 전역 객체 프로퍼티가 생성된다. foo() 함수 호출 시 this.a는 전역 객체 a다. 기본 바인딩이 적용되어 this는 전역 객체를 참조한다. 하지만 엄격 모드에서는 전역 객체가 기본 바인딩 대상에서 제외된다.

 

2. 암시적 바인딩

 

 두 번째 규칙.

호출부에 콘텍스트 객체가 있는지, 즉 객체의 소유/포함 여부를 확인하는 것이다.

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

var obj = {
    a : 2,
    foo: foo
};

obj.foo();  // 2

 

위 예제에서 foo() 호출 시점에 이미 obj 객체 레퍼런스는 준비된 상태다. 함수 레퍼런스에 대한 콘텍스트 객체가 존재할 때 암시적 바인딩 규칙에 따르면 바로 이 콘텍스트 객체가 함수 호출 시 this에 바인딩된다. foo() 호출 시 obj는 this이니 this.a는 obj.a가 된다.

 

3. 명시적 바인딩

 

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

var obj = {
    a : 2
};

foo.call(obj);  // 2

 

 위 예제에서 foo.call(..)이라는 함수를 썼다. foo.apply(..)함수를 쓸 수도 있는데, 두 메서드는 this에 바인딩할 객체를 첫째 파라미터로 받아 함수 호출 시 이 객체를 this로 세팅한다. this를 지정한 객체로 직접 바인딩하므로 '명시적 바인딩'이라 한다.

 

- 하드 바인딩

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

var obj = {
    a : 2
};

var bar = function() {
  foo.call(obj);
};

bar(); // 2
setTimeout(bar, 100); // 2

// 하드 바인딩된 bar에서 재정의된 this는 의미 없다.
bar.call(window); // 2

 

 함수 bar()는 내부에서 foo.call(obj)를 호출하면서 obj를 this에 강제로 바인딩하도록 하드 코딩한다. 따라서 bar를 어떻게 호출하든 이 함수는 항상 obj를 바인딩하여 foo를 실행한다.

 

4. new 바인딩

 

 네 번째 바인딩 규칙.

함수 앞에 new를 붙여 생성자 호출을 하면 다음과 같은 일들이 일어난다.

 

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

2. 새로 생성된 객체의 [[Prototype]]이 연결된다.

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

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

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

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

 

 위 예제에서 앞에 new를 붙여 foo(..)를 호출했고, 새로 생성된 객체는 foo 호출 시 this에 바인딩된다. 

 

 

** 바인딩 우선순위 : 명시적 바인딩 > new 바인딩 > 암시적 바인딩 > 기본 바인딩

 

5. 바인딩 예외

 

 특정 바인딩을 의도했는데 실제로는 기본 바인딩 규칙이 적용되는 예외 사례이다.

 

A. this 무시

 

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

var a = 2;
foo.call(null); // 2

 

 위 예제처럼 call, apply, bind 메서드에 첫 번째 파라미터로 null 또는 undefined를 넘기면 this 바인딩이 무시되고 기본 바인딩 규칙이 대신 적용된다.

 

B. 간접 레퍼런스

 

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

 

 할당 표현식 p.foo = o.foo의 결과값은 원 함수 객체의 레퍼런스이므로 실제로 호출부는 foo()이다. 그러므로 기본 바인딩 규칙이 적용된다.

 

C. 소프트 바인딩

 

 암시적/명시적 바인딩 기법을 통해 임의로 this 바인딩을 하는 동시에 전역 객체나 undefined가 아닌 다른 기본 바인딩 값을 세팅할 수 있도록 고안해 낸 것을 소프트 바인딩이라 한다.

 

 

 

 

 

 

 

참조 저서 : 카일 심슨, You Don't Know JS this & Object Prototypes, 한빛미디어, 32

반응형