Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

나나나

[Javascript] Javascript에서의 this 본문

언어

[Javascript] Javascript에서의 this

Leenk 2021. 6. 9. 22:25

1. This

자바스크립트의 this 키워드는 자신이 속한 객체를 참조한다.

  • Javascript에는 전역스크립트나 함수가 실행될 때 실행 문맥(Execution context)가 생성된다.
  • 모든 context에는 참조하고 있는 객체(this binding)가 존재하는데, 현재 context가 참조하고 있는 객체를 알기 위해 this를 사용한다.
  • 자바스크립트의 함수는 호출될 때, 매개변수로 전달되는 인자값과 arguments객체, this를 암묵적으로 전달받는다.
  • 이 때, this에 바인딩되는 객체는 함수 호출 방식에 따라 this에 바인딩되는 객체가 달라진다.
  • this binding은 함수를 호출할 때 함수가 어떻게 호출되었는지에 따라 this에 바인딩할 객체가 동적으로 결정되는 것을 말한다.
    • 참고 : 함수의 상위 스코프를 결정하는 방식인 렉시컬 스코프는 함수를 선언할 때 결정된다. (this 바인딩과 별개)

2. 함수의 호출 방식 (기본 바인딩)

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

1) 함수 호출

  • 글로벌 영역에 선언한 함수는 전역 객체의 프로퍼티로 접근할 수 있는 전역 변수의 메소드이다.
    • 전역 객체 : 모든 객체의 유일한 최상위 객체(브라우저 - window / 서버 - global)
// browser
console.log(this === window) // true

// node
console.log(this === global) // true
  • 전역 객체는 전역 스코프를 갖는 전역변수를 프로퍼티로 소유한다.
  • 함수 호출로 전역 객체에 바인딩 되는 경우
    • 전역 함수
    • 내부 함수(일반 함수, 메소드, 콜백함수 속 내부 함수)
    • 콜백함수
function foo() {
    console.log(this); // 전역 객체
    function inner() {
        console.log(this); // 전역 객체
    }
}

2) 메소드 호출 (암시적 바인딩)

  • 함수가 객체의 프로퍼티 값이면 메소드로서 호출된다. 이때 메소드의 this는 해당 메소드를 소유한(호출한) 객체에 바인딩된다. 프로토타입 객체도 마찬가지이다.
var obj = {
    value = 100,
    foo: function() {
        console.log(this); // obj
        function bar() {
            console.log(this); // 전역 객체(메소드의 내부 함수이므로)
        }
    }
}

3) 생성자 함수 호출(new 연산자와 함께 생성자 함수 호출) 과 동작 방식

  1. 빈 객체 생성 및 this 바인딩
    • 생성자 함수의 코드가 실행되기 전 생성된 빈 객체로 생성자 함수 내에서 사용되는 this는 이 빈 객체를 가리킨다. 
  2. this를 통한 프로퍼티 생성
    • 생성된 빈 객체에 this를 사용하여 동적으로 프로퍼티나 메소드를 생성할 수 있으며, this는 새로 생성된 객체를 가리키므로 this를 통해 생성한 프로퍼티와 메소드는 새로 생성된 객체에 추가된다.
  3. 생성된 객체 반환
    • 반환문이 없는 경우, this에 바인딩된 새로 생성된 객체가 반환된다(명시적으로 this를 반환한 것과 결과 동일)
      • 반환문이 this가 아닌 다른 객체를 명시적으로 반환하면, this를 반환하지 않은 함수는 생성자 함수의 역할을 수행하지 못한다. 따라서 생성자 함수는 반환문을 명시적으로 사용하지 않는다.

4) apply / call / bind (명시적 바인딩)

  • apply / call
    • 자바스크립트 엔진의 암묵적 this 바인딩 이외에 this를 특정 객체에 명시적으로 바인딩하는 방법
    • 첫번째 인자로 넘겨주는 것이 this context 객체가 된다.
    • 메소드를 호출하는 주체는 함수이며, 메소드는 this를 특정 객체에 바인딩할 뿐 본질적인 기능은 함수 호출이다.
// call 또는 apply의 첫 번째 인자로 객체가 전달될 수 있으며 this가 그 객체에 묶임
var obj = {a: 'Custom'};

// 변수를 선언하고 변수에 프로퍼티로 전역 window를 할당
var a = 'Global';

function whatsThis() {
  return this.a;  // 함수 호출 방식에 따라 값이 달라짐
}

whatsThis();          // 'Global'. 함수 내에서 설정되지 않았으므로 global/window 객체로 초기값을 설정한다.
whatsThis.call(obj);  // 'Custom'. 함수 내에서 obj로 설정한다.
whatsThis.apply(obj); // 'Custom'. 함수 내에서 obj로 설정한다.


//////


function add(c, d) {
  return this.a + this.b + c + d;
}

var o = {a: 1, b: 3};

// 첫 번째 인자는 'this'로 사용할 객체이고,
// 이어지는 인자들은 함수 호출에서 인수로 전달된다.
add.call(o, 5, 7); // 16

// 첫 번째 인자는 'this'로 사용할 객체이고,
// 두 번째 인자는 함수 호출에서 인수로 사용될 멤버들이 위치한 배열이다.
add.apply(o, [10, 20]); // 34
  • bind 
    • 함수에 인자로 전달한 this가 바인딩된 새로운 함수를 리턴한다.
    • call, apply처럼 함수를 실행하지 않기 때문에 명시적으로 함수를 호출할 필요가 있다.
    • 호출 방식과 상관없이 영구적으로 bind()의 첫 번째 매개변수로 고정된다.
function f() {
  return this.a;
}

var g = f.bind({a: 'azerty'});
console.log(g()); // azerty

var h = g.bind({a: 'yoo'}); // bind는 한 번만 동작함!
console.log(h()); // azerty

var o = {a: 37, f: f, g: g, h: h};
console.log(o.a, o.f(), o.g(), o.h()); // 37, 37, azerty, azerty

 

정리

호출 방식과 상황 this
전역 문맥에서의 this 호출 전역 객체(서버: global object /브라우저: window 객체)
함수 전역 객체(서버: global object /브라우저: window 객체)
함수 + strict mode undefined(실행 문맥에 진입하여 설정되는 값 유지)
메소드 호출 해당 메소드를 소유한 객체
new 생성자 새로 생긴 객체
call/apply 첫 번째 인자(한 문맥에서 다른 문맥으로 넘기기)
bind bind() 호출의 첫 번째 매개변수로 고정
이벤트 핸들러 이벤트를 받은 element
화살표 함수(arrow function) 자신을 감싼 정적 범위(lexical context) / 전역에서는 전역 객체

 

 

 

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this

https://www.w3schools.com/js/js_this.asp

https://poiemaweb.com/js-this