개발/Javascript(Typescript)

자바스크립트 this

piece5 2023. 7. 14. 23:53

this 키워드는 자바스크립트에서 다른 언어와 다르게 작동한다. strict mode일 때와 아닐 때도 차이가 있다.

bind() 메소드는 어떻게 그것을 호출했는지와 상관 없이 this 값을 설정할 수 있다. 그리고 화살표 함수는 this 바인딩을 제공하지 않는다.

 

전역 실행 맥락에서 this는 엄격 모드 여부에 관계 없이 전역 객체를 참조합니다.

웹브라우저에서 this는 window를 가리킵니다.

 함수

function f1() {
  return this;
}

// 브라우저
f1() === window; // true

// Node.js
f1() === global; // true

function f2(){
  "use strict"; // 엄격 모드
  return this;
}

f2() === undefined; // true

call(), apply()

// call 또는 apply의 첫 번째 인자로 객체가 전달될 수 있으며 this가 그 객체에 묶임
var obj = {a: 'Custom'};

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

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

whatsThis();          // this는 'Global'. 함수 내에서 설정되지 않았으므로 global/window 객체로 초기값을 설정한다.
whatsThis.call(obj);  // this는 'Custom'. 함수 내에서 obj로 설정한다.
whatsThis.apply(obj); // this는 '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

비엄격 모드에서 this로 전달된 값이 객체가 아닌 경우, call apply는 이를 객체로 변환하기 위한 시도를 합니다. 

null undefined 값은 전역 객체가 됩니다. 

7이나 'foo'와 같은 원시값은 관련된 생성자를 사용해 객체로 변환된다.

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

bar.call(7);     // [object Number]
bar.call('foo'); // [object String]
bar.call(undefined); // [object global]

bind()

f.bind(someObject)를 호출하면 this는 원본 함수를 가진 새로운 함수를 생성합니다. 새 함수의 this는 호출 방식과 상관없이 영구적으로 bind()의 첫 번째 매개변수로 고정됩니다.

function f() {
  return this.a;
}

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

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

var i = h.bind({a: 'fff'});
console.log(i()); // yoo

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

화살표 함수

화살표 함수를 call(), bind(), apply()를 사용해 호출할 때 this의 값을 정해주더라도 무시합니다. 어떤 방법을 사용하든 함수 this는 생성 시점의 것으로 설정됩니다. 사용할 매개변수를 정해주는 건 문제 없지만, 첫 번째 매개변수(thisArg)는 null을 지정해야 합니다.

 

객체의 메소드

함수가 정의된 방법이나 위치에 전혀 영향을 받지 않는 것에 유의해라.

아래에서 independent 함수가 나중에 객체에 포함되어도 this가 그 객체를 가리키며 객체안의 객체에 포함되면 객체안의 객체를 가리킨다.

const test = {
  prop: 42,
  func: function() {
    return prop; // 그냥 접근 불가능, test.prop 또는 this.prop으로 접근 가능하다.
  },
};

console.log(test.func());


var o = {prop: 37};

function independent() {
  return this.prop;
}

o.f = independent;

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


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

객체의 프로토타입 체인에서의 this

함수 f 는 p 의 메소드로서 호출된 이후로, this 는 p 를 나타낸다. 이것은 JavaScript 의 프로토타입 상속의 흥미로운 기능이다.

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

DOM 이벤트 처리기

함수를 이벤트 처리기로 사용하면 this는 이벤트를 발사한 요소로 설정됩니다. 일부 브라우저는 addEventListener() 외의 다른 방법으로 추가한 처리기에 대해선 이 규칙을 따르지 않습니다.

 

인라인 이벤트 핸들러

두번째 경우에 this는 window를 가리킨다. 첫번째 경우에 올바르게 현재 버튼을 가리킨다.

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

<button onclick="alert((function() { return this; })());">
  내부 this 표시
</button>

 

다음~

생성자, 접근자, 설정자~

 

출처

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