this

공헌자 숫자: 3명

요약

javascript에서 함수의 this 키워드는 다른 언어들과 비교하여 조금 다르게 동작한다. 또한 strict mode와 non-strict mode 사이에서도 조금 다르다.

대부분의 경우, this 의 값은 함수를 호출하는 방법에 의해 결정된다. 실행하는 동안의 할당에 의해 설정될수 없고, 함수가 호출될 때 마다 다를 수 있다. ES5 는 함수의 this 값이 함수가 어떻게 호출되었는지 개의치 않고 설정할 수 있는 bind 메소드를 소개했다.

구문

this

전역 컨텍스트

전역 실행 컨텍스트(어떤 함수의 외부)에서는, this는 strict mode이거나 아니여도 전역 객체를 나타낸다.

console.log(this.document === document); // true

// 웹 브라우저에서, window 객체는 전역 객체이다 :
console.log(this === window); // true

this.a = 37;
console.log(window.a); // 37

함수 컨텍스트

함수 내부에서, this는 함수를 호출한 방법에 의해 좌우된다.

간단한 호출

function f1(){
  return this;
}

f1() === window; // global object

이 경우, this의 값은 호출에 의해 설정되지 않는다. 이 코드는 strict mode가 아니기 때문에, this의 값은 항상 전역 객체에서 기본이 되는 객체여야 한다.

function f2(){
  "use strict"; // see strict mode
  return this;
}

f2() === undefined;

strict mode에서는, this의 값은 실행 컨텍스트 들어갈 때 할당되어 유지된다. 만약 정의 되지 않았다면, undefined가 유지된다. 게다가 null 또는 42 또는 "I am not this" 등  어떤 값이던 설정할 수 있다. 

Note: 두번째 예제에서, thisundefined 일것이다, 왜냐하면 f2가 어떠한 기본(예. f2())도 제공하지 않고 호출했다. 이 기능은 strict mode를 지원하기 위해  시작했을 때 일부 브라우저에서 구현되지 않았다. 결과적으로, window 객체를 잘못 반환했다.

객체의 메소드로서

함수가 한 객체의 메소드로 호출되었을 때, this는 메소드가 호출된 객체가 할당됩니다.

다음 예제에서, o.f() 가 실행될 때, 함수 안쪽의 thiso 객체가 연결된다.

var o = {
  prop: 37,
  f: function() {
    return this.prop;
  }
};

console.log(o.f()); // logs 37

this 동작이 함수가 정의된 방법이나 위치에 전혀 영향을 받지 않는 것에 유의해라.  이전 예제에서, o 의 정의 중 f 함수를 구성원으로 내부에 정의 하였다.  그러나, 간단하게 함수를 먼저 정의하고 나중에 o.f를 추가할 수 있다. 이렇게 하면 동일한 동작 결과 이다 :

var o = {prop: 37};

function independent() {
  return this.prop;
}

o.f = independent;

console.log(o.f()); // logs 37

이는 함수가 o의 멤버 f로 부터 호출 된 것만이 중요하다는 것을 보여준다.

마찬가지로, 이 this 바인딩은 가장 즉각으로 멤버 대상에 영향을 받는다. 다음 예제에서, 함수를 실행할 때, 객체 o.b의 메소드 g 로서 호출한다. 이것이 실행되는 동안, 함수 내부의 thiso.b를 나타낸다. 객체는 그 자신이 o의 멤버 중 하나라는 사실은 중요하지 않다. 가장 즉각적인 참조가  중요한 것이다.

o.b = {g: independent, prop: 42};
console.log(o.b.g()); // logs 42

객체의 prototype 체인에서 this

같은 개념으로 객체의 prototype 체인 어딘가에 정의된 메소드도 마찬가지이다. 메소드가 한 객체의 prototype 체인에 있다면, 마치 메소드는 객체에 있는 것 처럼 this는 메소드가 호출된 객체를 나타낸다.

var o = {f:function(){ return this.a + this.b; }};
var p = Object.create(o);
p.a = 1;
p.b = 4;

console.log(p.f()); // 5

이 예제에서, f 속성을 가지고 있지 않은 변수 p가 할당된 객체는, prototype으로 부터 상속받는다. 그러나 그것은 결국 o에서 f 이름을 가진 멤버를 찾는 되는 문제가 되지 않는다 ; p.f를 찾아  참조하기 시작하므로, 함수 내부의 this p 처럼 나타나는 객체 값을 취한다. 즉, fp의 메소드로서 호출된 이후로, thisp를 나타낸다. 이것은 Javascript의 prototype 상속의 흥미로운 기능이다.

getter와 setter에서의 this

다시, 함수가 getter와 setter에서 호출될 때도 같은 개념이다. getter와 setter로 사용되는 함수의 this는 set 또는 get 되는 속성 객체로 연결된다. 

function modulus(){
  return Math.sqrt(this.re * this.re + this.im * this.im);
}

var o = {
  re: 1,
  im: -1,
  get phase(){
    return Math.atan2(this.im, this.re);
  }
};

Object.defineProperty(o, 'modulus', {
    get: modulus, enumerable:true, configurable:true});

console.log(o.phase, o.modulus); // logs -0.78 1.4142
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

생성자로서

함수가 생성자로서 사용될 때(new 키워드와 함께),  this 는 새롭게 생성된 객체에 연결된다.

Note: 생성자의 기본은 this에 의해 참조되는 객체를 반환하지만, 가끔 다른 객체를 대신 반환할 수도 있다.(반환 값이 객체가 아닌 경우, this 객체를 반환한다.)

/*
 * 생성자는 이와 같이 작동한다:
 *
 * function MyConstructor(){
 *   // 실제 함수 본문 코드가 에기에 표시된다.  
 *   // this에 할당하여 원하는 대로 속성을 만들 수 있다. 예를 들어,
 *   this.fum = "nom";
 *   // 등등...
 *
 *   // 함수가 객체를 반환하는 return 문이 있다면,
 *   // 그 객체는 |new| 표현식의 결과가 될 것이다.
 *   // 그렇지 않다면,
 *   // 표현식의 결과는 현재 |this|에 연결된 객체이다.
 *   // (즉, 일반적 경우 대부분 이런 것을 볼 수 있다.).
 * }
 */

function C(){
  this.a = 37;
}

var o = new C();
console.log(o.a); // logs 37


function C2(){
  this.a = 37;
  return {a:38};
}

o = new C2();
console.log(o.a); // logs 38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

마지막 예제에서 (C2), 이 객체는 생성하는 동안 return 되었기 때문에, this에 연결된 새로운 객체는 그냥 버려진다. (이것은 본질적으로 "this.a = 37;"가 죽은 코드를 만든다. 그것은 실행되지 때문에 명확히는 죽은 것은 아니지만, 어떤 외부 영향을 받지 않는다.)

call 그리고 apply

함수의 본문(내부)에서 this 키워드를 사용하는 경우, Function.prototype으로 부터 상속되는 함수의 Function.call()Function.apply()를 사용하여 호출하면 특정한 객체와 연결된다.

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

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

// 첫번째 매개 변수는 'this'로 사용할 객체이고,
// 다음 매개 변수들은 호출되는 함수에 인수로 전달된다.
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16

// 첫번째 매개 변수는 'this'로 사용할 객체이고,
// 두번째는 호출되는 함수에 인수로 사용되는 멤버들의 배열이다.
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

callapply에서 주의할 것은, this를 나타내는 값이 객체가 아니라면, 내부 ToObject를 이용하여 객체로 변환 될 것이다. 그래서 '7' 또는 'foo' 같은 기본 형태의 값이 전달되면, 연관된 생성자를 사용하여 객체로 변환할 것할 것이다. 기본 숫자 7new Number(7), 문자 'foo'new String('foo')를 사용하여 객체로  변환된다. 예를 들어,

function bar() {
  console.log(Object.prototype.toString.call(this));
}

bar.call(7); // [object Number]
 
 
 
 
 

bind 메소드

ECMAScript 5는 Function.prototype.bind를 도입했다. f.bind(객체)를 호출하면 같은 본문(코드)과 asf 생명주기로 새로운 함수를 생성한다. 원래의 함수에서 발생하는 this 지만, 함수가 어떻게 사용되고 있는지 개의치 않고, 새로운 함수에서 this는 bind의 첫번째 인수로 영구적으로  연결된다

function f(){
  return this.a;
}

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

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

DOM 이벤트 핸들러로서

함수가 이벤트 핸들러로 사용될 때는, this는 이벤트가 발생한 엘리먼트로 설정된다. (몇몇 브라우저들은 리스너를 addEventListener 이외의 방법으로 동적으로 추가하기 위하여 이 관습을 따르지 않는다.)

// 리스너로서 호출될 때, 관련된 엘리먼트를 파랗게 만든다.
function bluify(e){
  // 항상 true
  console.log(this === e.currentTarget); 
  // currentTarget 과 target 이 같은 객체일 때 true
  console.log(this === e.target);
  this.style.backgroundColor = '#A5D9F3';
}

// document의 모든 엘리먼트의 목록을 얻는다.
var elements = document.getElementsByTagName('*');

// 클릭 리스너로 bluify를 추가하여서 엘리먼트를 클릭하면, 그 엘리먼트는 파랗게 된다.
for(var i=0 ; i<elements.length ; i++){
  elements[i].addEventListener('click', bluify, false);
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

in–line 이벤트 핸들러에서

코드가 in-line 핸들러에서 호출 될 때, this는 리스너가 위치한 DOM 엘리먼트가 할당된다:

<button onclick="alert(this.tagName.toLowerCase());">
  Show this
</button>
 
 
 

위의 alert는 button이 보여진다. 참고로 오직 외부 코드에서 this를 할당 할 수 있다:

<button onclick="alert((function(){return this}()));">
  Show inner this
</button>
 
 
 

이 경우에서는, 함수 내부의 this 할당 되지 않았으므로 전역/window 객체가 반환된다. (즉, this는 호출에 의해 할당되지 않고 non-strict mode의 기본 객체).

설계 명세

Specification Status Comment
ECMAScript 1st Edition. Standard 초기 정의. JavaScript 1.0에서 구현
ECMAScript 5.1 (ECMA-262)
The definition of 'The this keyword' in that specification.
Standard  
ECMAScript 6 (ECMA-262)
The definition of 'The this keyword' in that specification.
Release Candidate  

브라우저 호환성

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support (Yes) (Yes) (Yes) (Yes) (Yes)
Feature Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Basic support (Yes) (Yes) (Yes) (Yes) (Yes) (Yes)

참조

문서 태그 및 공헌자

Contributors to this page: teoli, eros21c, Channy
최종 변경: teoli,
사이드바 숨기기