[JavaScript] this

s0zzang·2023년 5월 24일
1
post-thumbnail

this 정의

  • javascript의 this 는 다른 언어와 다르게 동작, 엄격모드와 비엄격모드에서도 차이가 있음
  • 실행 컨텍스트 내에서 현재 실행중인 함수, 메서드를 소유하고 있는 객체를 참조하는 특별한 키워드
  • 함수 호출 방식에 따라, this 에 바인딩할 어떤 객체가 동적으로 결정됨

    🔥 함수 선언이 아닌, 호출할 때 this에 바인딩할 객체가 동적으로 결정 !



실행 컨텍스트 (Execution Context)

1. 실행 컨텍스트란?

실행 컨텍스트 = 문맥, 코드의 실행 환경

  • 자바스크립트 코드가 실행되고 연산되는 범위를 나타내는 추상적인 개념
  • 실행 컨텍스트가 활성화 되는 시점에 생기는 현상
    - 호이스팅 발생 | 외부 환경 정보 구성 | this 값 설정

2. 실행 컨텍스트 분류

1) Global Execution Context

  • 코드가 실행되는 영역
  • 글로벌 객체인 window 객체를 생성, this를 글로벌 객체로 설정

    this 출력 : window

2) Functional Execution Context

  • 각각의 함수가 가지는 실행 컨텍스트
  • 함수가 호출될 때 해당 실행 컨텍스트가 생성


함수 호출 방식과 this 바인딩

1. 바인딩

  • 식별자와 값을 연결하는 과정
    🍀 예시 : 변수선언 = 변수 이름과 확보된 메모리 공간의 주소를 바인딩하는 것
    🍀 this 바인딩 : this와 this가 가리킬 객체를 바인딩

this의 값이 호출되는 방법에 의해 결정되기 때문에, 호출방법과 무관하게 this를 고정시키기 위해 바인드를 사용해야 한다.

2. 함수 호출 방식

  • 일반 함수 호출 (defalut 바인딩)

  • 객체의 메서드 호출 (암시적 바인딩)

  • apply | call | bind 호출 (명시적 바인딩)

  • 생성자 함수 호출 (new 바인딩)

    var foo = function () {
      console.dir(this);
    };
    
    // 1. 일반 함수 호출 (defalut 바인딩)
    foo(); // window
    // window.foo();
    
    // 2. 객체의 메서드 호출 (암시적 바인딩)
    var obj = { foo: foo };
    obj.foo(); // obj
    
    // 3. 생성자 함수 호출 (new 바인딩)
    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

2-1) 일반 함수 호출 (defalut 바인딩)

// in browser console
this === window // true
console.log(this) // Window {0: Window, 1: global, 2: global, …}


// in Terminal
node
this === global // true
  • this : 전역객체 에 바인딩
  • 전역 개체 : 모든 객체의 유일한 최상의 객체를 의미, 전역 범위에 항상 존재하는 객체
    🍀 브라우저의 전역객체 : window
    🍀 서버/터미널(node)의 전역객체 : global

콘솔창에 this를 찍으면 window가 나오는데, this는 javascript 실행 환경의 전역 객체라고 할 수 있다. 전역객체 (window, global)는 일반 객체처럼 제약 없이 동작하기 때문에 this를 무분별하게 사용하면 전역 상태에 영향을 줄 수 있으므로 주의해야 한다.

일반 함수 내에서 this를 호출하면 역시 this는 전역 객체(window)가 바인딩 된다. 이때 this의 객체(window)는 객체의 프로퍼티나 메서드를 참조하기 위한 변수여서, 일반 함수에서의 this는 의미가 없다.

콜백 함수가 일반 함수로 호출된다면 콜백 함수 내부의 this도 전역 객체(window)가 바인딩 된다. 즉 어떤 함수라도 일반 함수로 호출되는 경우 ! this 는 전역 객체에 바인딩 된다 !


2-2) 객체의 메서드 호출 (암시적 바인딩)

const person ={
	name : "Kim",
    getName() {
      return this.name;
    }
};
 
console.log(person.getName()); // Kim

객체의 메서드 호출시 this : 해당 객체

간단하게 어떤 객체를 통해 함수가 호출되면 그 객체가 바로 this의 컨텍스트 객체가 된다. person 객체를 통해 getName 함수가 호출되었기 때문에 this는 person 객체에 바인딩 되는 것 !

메서드는 프로퍼티에 바인딩 된 함수를 의미하는데, getName 프로퍼티가 가리키는 함수 객체는 person 객체에 포함된게 아니라 독 ! 립 ! 적으로 존재하는 별도의 객체다.

프로퍼티?

다른 값과 연관되어 있는 어떤 값, 객체 내 프로퍼티 키: 프로퍼티 값으로 저장됨

  • name = 프로퍼티 키
  • "kim" = 프로퍼티 값

메서드를 다른 객체 프로퍼티에 할당하기

const anotherPerson = {
  name: "Lee",
};
 
// getName 메서드를 anotherPerson 객체의 메서드로 할당
anotherPerson.getName = person.getName;
 
// getName 메서드를 호출한 객체는 anotherPerson
console.log(anotherPerson.getName()); // Lee
 
// getName 메서드를 일반 함수에 할당하고, 호출
const getName = person.getName();
console.log(getName()); // ''

위의 코드처럼 다른 객체(anotherPerson)의 프로퍼티에 할당하여 다른 객체의 메서드가 될 수도, 일반 변수에 할당하여 일반 함수로 호출될 수 있다.


2-3) apply | call | bind 호출 (명시적 바인딩)

apply, call, bind는 Function.prototype의 메서드이다. 이런 메서드는 모든 함수가 상속받아 사용할 수 있고 함수가 첫번째 인자로 넘겨주는 값이 this의 컨텍스트 객체가 된다.

call & apply

call, apply는 this를 특정 객체에 바인딩해주며 함수를 호출한다.
call은 인자를 하나씩 넣어줘야하고 apply는 배열 형태로 넣어주면 된다.

function hello(message) {
  console.log(`안녕 나는 ${this.name}`);
  console.log(message);
}
const person1 = {
  name: "철수"
};

hello("만나서 반가워"); // this: 전역객체 바인딩 => 안녕 나는 () 만나서 반가워
hello.call(person1, "만나서 반가워!"); // this: 명시적 바인딩 => 안녕 나는 철수 만나서 반가워
hello.apply(person1, ["만나서 반가워!"]); // this: 명시적 바인딩 => 안녕 나는 철수 만나서 반가워

bind

call, apply와 비슷하지만 bind는 this에 바인딩하는 역할을 위해 만들어졌다. call, apply와 같이 함수를 호출하는 것이 아니라, this가 바인딩된 새로운 함수를 반환한다.
함수 호출이 아닌 함수 반환이기 때문에 콜백 함수를 등록할 때 사용하기도 한다.

function hello(message) {
  console.log(`안녕 나는 ${this.name}`);
  console.log(message);
}
const person1 = {
  name: "철수"
};

const bindedHello = hello.bind(person1, "만나서 반가워");
bindedHello();
hello.bind(person1, "만나서 반가워")(); // 안녕 나는 철수 만나서 반가워

2-4) 생성자 함수 호출 (new 바인딩)

생성자 함수는 객체를 생성하는 함수이다. 생성자 함수를 통해 만들어진 객체의 this는 해당 인스턴스가 바인딩 된다.

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

const 철수 = new Person("철수");
console.log(철수); // Person {name: "철수"}
profile
" 퍼블리셔에서 프론트엔드로 Level up 중 ... 💨 "

0개의 댓글