Code

JavaScript this 정리

March 10, 2016

JavaScript this 정리

JavaScript에서 this 키워드는 흔히 객체지향적으로 자바스크립트를 작성할 때 종종 사용되곤 한다. 하지만 학부생 수준에서 배우게 되는 다른 객체지향언어(C++ / Java)와는 여러가지 상이한 점이 존재한다.

다음은 평범한 this의 용례다.

function Person(name, age) {
  this.name = name;
  this.age = age;
}

var hyunseob = new Person('이현섭', 27);
console.log(hyunseob.name); // 이현섭
console.log(hyunseob.age);  // 27

생성자(constructor)로서 사용하게 되면 다른 객체지향 언어와 비슷한 방식. 즉, 생성된 객체의 멤버변수를 참조하게 된다. 이것은 prototype을 사용해서 정의한 객체의 메소드에서도 동일하다.

// 위 코드에 이어서
Person.prototype.isYoung = function() {
  return this.age < 25;
}

console.log(hyunseob.isYoung()); // false

하지만 this 키워드는 기본적으로 전역객체(브라우저에서는 window와 같다.)이므로 굳이 위와 같이 객체 메소드 내부에서 호출하지 않아도 사용할 수 있다.

console.log(this.hyunseob.isYoung()); // false
console.log(window === this)          // true

this를 생성자 혹은 객체의 메소드에서 사용하지 않는 경우 this는 전역객체가 된다.

var seungmin = Person('이승민', 28);

console.log(seungmin); // undefined
console.log(name);     // 이승민
console.log(age);      // 28

위에서는 Person 함수를 new 키워드 없이 사용.. 즉, 생성자로 사용하지 않았기 때문에 this가 전역객체가 되었고, 덩달아 nameage는 전역변수가 된 것이다. 더구나 Person 함수는 리턴하는 값이 없기 때문에 seungmin이라는 변수는 값이 초기화 되지 않았다. 미안해요 승민이형

특히, strict mode를 사용해서 함수를 정의하는 경우에는 다음과 같이 thisundefined 값이 된다.

function returnThis() {
  return this;
}

function returnThisStrict() {
  'use strict';
  return this;
}

console.log(returnThis() === this);       // true
console.log(returnThisStrict() === this); // false
console.log(returnThisStrict());          // undefined

하지만 strict mode로 정의한 함수라도 특정 객체의 메소드로 호출된다면 this는 호출한 객체를 참조하게 된다.

console.log(window.returnThisStrict() === window); // true

또한, 다음과 같이 apply를 사용해서 내가 원하는 값을 this로 던져줄 수 있다.

var jaehoon = {};
Person.apply(jaehoon, ['석재훈', 28]);

console.log(jaehoon.name); // 석재훈
console.log(jaehoon.age);  // 28

이것은 call을 사용해도 똑같이 구현할 수 있다.

var hosuk = {};
Person.call(hosuk, '신호석', 24);

console.log(hosuk.name); // 신호석
console.log(hosuk.age);  // 24

callapplythis로 넘겨지는 값이 객체가 아닐 때 자동으로 객체로 변환하므로 조심해야 한다. 또한 만약 thisnull 혹은 undefined같은 값을 넘기는 경우 this는 전역객체를 참조한다.

ES5에서는 this값을 넘기기 위해서 bind를 사용할 수도 있다. 이것은 ES6-cheatsheet에서 언급한 예에서 처럼 중첩된 함수 내에서 this의 컨텍스트를 보존하는 용도로 종종 사용된다.

var heeduk = {};
Person.bind(heeduk)('이희덕', 30);

console.log(heeduk.name); // 이희덕
console.log(heeduk.age);  // 30

참고링크