this, binding

이재홍·2022년 6월 27일
0

Basic JS

목록 보기
16/18
post-thumbnail

https://medium.com/sjk5766/javascript-this-binding-%EC%A0%95%EB%A6%AC-ae84e2499962

this

JavaScript 에서 함수의 this 키워드는 다른언어와 조금 다르게 작동한다고 한다.

this와 실행 컨텍스트
자바스크립트는 스크립트 언어로, 인터프리터에 의해 줄 단위로 읽혀서 해석 실행됨

인터프리터에 의해 현재 실행되는 JS의 환경을 실행 컨텍스트라고 함!
자바스크립트 내부에서 이러한 실행 컨텍스트를 스택으로 관리하고, 실행되는 시점에 자주 변경되는 실행컨텍스트를 this가 가리킨다!

this Binding 정리

1. default binding

: 기본적으로 this는 전역 객체를 가리키게 되는데 Node 환경에서는 global 객체,Browser에서는 Window 객체를 가리킴!

  • Browser
  • Node

2. 함수 내부의 this binding

: 일반적인 함수 내부에서 this를 호출하면 전역 객체!
, strict 모드를 사용하는 경우에는 그렇지 않음 (undefined 반환됨)
즉시 실행함수의 경우에도 마찬가지!

function checkThisInNormalFunc() {
    console.log(this === window) // true
}
checkThisInNormalFunc()
console.log(this === window)     // true

// strict 모드
function checkThisInNormalFunc() {
    'use strict';
    console.log(this === window) // false
}
checkThisInNormalFunc()
console.log(this === window)     // true

3. 객체의 메소드 this binding

객체 내부의 메소드에서 this를 binding 할 경우, 그 객체 자신을 가리키게 됨
this가 참조되는 위치가 중요한게 아니라 어디서 어떻게가 this를 포함하는 코드를 호출하냐가 중요!

var obj1 = {
    name: "seo",
    print: function() {
      console.log(this.name);   // this가 참조되는 위치
    }
}
var obj2 = { name: "jeong", print: obj1.print };
var name = "kuk";
var print = obj1.print;
print();           // kuk 일반적인 함수호출 (this는 전역객체)
obj1.print();      // jeong (객체 메소드 방식으로 호출)
obj2.print();      // seo (객체 메소드 방식으로 호출)

4. new 키워드와 this binding

함수 내부에서 this는 전역 객체를 가리킴!

function printName() {
    var lastName = "seo";
    this.firstName = "jeong kuk"
    console.log(this.lastName + " " + this.firstName)
}
var lastName = "kim";
printName();               // kim jeong kuk
var o = new printName();   // undefined jeong kuk

printName 함수 안에 lastName과 this로 접근함 firstName이 있음
firstName은 전역객체! (함수내부 this = 전역객체)

대신 new를 선언할 경우 this 는 전역객체가 아닌 생성된 객체 자체를 가리키게됨
따라서 this로 접근한 firstName은 정상적인 값을 가져오지만 더 이상 전역객체가 아니어서 lastName은 undefined로 나옴

call, apply 메소드와 this binding

call, apply 메소드는 첫 번째 인자로 실행 컨텍스트를 인자로 전달함

printName.call(obj) 에서 obj 를 전달할 때, this 가 obj의 실행 컨텍스트를 가리키게 됨

function printName() {    
    console.log(this.name)
}
var name = "seo"
printName();          // seo
var obj = {name: "jeong kuk"}
printName.call(obj);  // jeong kuk

화살표함수

es6 에서 추가된 화살표 함수 내부에서 this를 사용할 경우 , this에 바인딩할 객체가 정적으로 결정되기 때문에 call, apply, bind 로 this를 변경할 수 없음!

window.x = 1;
const normal = function () { return this.x; };
const arrow = () => this.x;

console.log(normal.call({ x: 10 })); // 10
console.log(arrow.call({ x: 10 }));  // 1

화살표 함수 내부의 this는 언제나 상위 스코프의 객체를 가리킴(lexical this: 문맥적 this), 때문에 콜백 함수로 사용하기 편리하지만 화살표 함수를 사용해서는 안되는 경우도 존재해서 주의!!!

화살표 함수로 메소드를 선언하는 것은 위험

객체의 메서드를 화살표 함수로 선언할 경우, this는 해당 객체가 아닌 전역 객체를 가리키게되므로 주의해야함
이 경우에는 es6의 축약 메소드 표현을 사용하는 것이 좋다.

var obj = {
    foo: "foo",
    print1: () => { console.log(this.foo) },
    print2 () { console.log(this.foo) }
}
obj.print1() // undefined
obj.print2() // foo

화살표 함수는 prototype 속성이 없다

var Foo = () => {}
console.log(Foo.prototype) // undefined
var foo = new Foo()	   // TypeError: Foo is not a constructor

0개의 댓글