[코어 자바스크립트] this

진형욱·2022년 7월 24일
0

this란

어디에서나 사용할수있는 this, 함수를 호출할 때 결정되고 '누가 나를 불렀느냐'를 뜻한다.
단독으로 쓰거나 함수 안에서 쓰거나 등 각 상황별로 this가 각 호출에 의해 바인딩이 된다.
즉, 선언이 아닌 호출에 따라 달라진다.

전역공간에서 this

전역 공간에서 this는 전역 객체를 가르키며
전역변수를 선언하면 자바스크립트 엔진은 이를 전역객체의 프로퍼티로 할당한다.

단독으로 쓴 this를 호출하는 경우에는 global object(window)를 가리킨다.
브라우저에서 호출하는 경우에는 [object Window]가 가르킨다.

var x = this;
console.log(x); //Window

함수 vs 메서드

어떤 함수를 실행하는 방법은 여러 가지가 있는데 가장 일반적인 방법은
함수로서 호출하는 경우와, 메서드로서 호출하는 경우이다.
함수와 메서드는 미리 정의한 동작을 수행하는 코드 뭉치로, 이 둘을 구분하는 차이는 독립성에 있다.

함수는 그 자체로 독립적인 기능을 수행하는 반면
메서드는 자신을 호출한 대상 객체에 관해 동작을 수행한다.

함수 내부에서의 this

함수 안에서 this는 함수의 주인에게 바인딩이 된다.
함수의 주인은 => window 객체

function myFunction() {
  return this;
}
console.log(myFunction()); //Window
var num = 0;
function addNum() {
  this.num = 100;
  num++;
  
  console.log(num); // 101
  console.log(window.num); // 101
  console.log(num === window.num); // true
}
 
addNum();

위 코드에서 this.num의 this는 window 객체를 가리킵니다.
따라서 num은 전역 변수를 가리키게 된다.

함수에서의 this는 전역 객체를 가르킨다.

메서드 내부에서의 this

메서드는 객체의 메서드로서 호출할 경우에만 메서드로 동작하고, 그렇지 않으면 함수로 동작한다.
쉽게 구분한다면 점(.) 표기법과 대괄호([]) 표기법으로 구분이 가능하다.

어떤 함수를 호출할 때 그 함수 이름앞에 객체가 명시돼 있는 경우에는 메서드로 호출,
그렇지 않은 모든 경우에는 함수로 호출한 것이다.

var func = function(x) {
  console.log(this.x);
};
func(1); // Window 
 
 
var obj = {
  method: func
};
obj.method(2); // { method: f} 2

4번 줄은 앞에 점이 없으니 함수로서 호출한것이고,
9번째 줄은 method앞에 점이 있으니 메서드로서 호출한것이다.

메서드로서 호출하는 경우 호출 주체는 바로 함수명(프로퍼티명) 앞의 객체이다.
점 표기법의 경우 마지막 점 앞에 명시된 객체가 곧 this가 되는것이다.

this 바인딩에 관해서는 함수를 실행하는 당시의 주변 환경 (메서드 내부인지, 함수 내부인지) 중요하지 않고, 오직 해당 함수를 호출하는 구문 앞에 또는 대괄호 표기가 있는지 없는지가 관건이다.


콜백함수

함수A의 제어권을 다른 함수(또는 메서드) B에게 넘겨주는 경우 함수 A를 콜백함수라고 한다.

콜백함수도 함수이기 때문에 this가 전역객체를 참조하지만
제어권을 받은 함수에서 콜백 함수에 별도로 this가 될 대상을 지정한 경우 그 대상을 참조하게 된다.


생성자함수

어떤 공통된 성질을 지니는 객체들을 생성하는데 사용하는 함수이다.

생성자 내부에서 쓴 this의 코드이다.

function Person(name) {
  this.name = name;
}
 
var kim = new Person('kim');
var lee = new Person('lee');
 
console.log(kim.name); //kim
console.log(lee.name); //lee

생성자 함수가 생성하는 객체로 this가 바인딩 된다.

var name = 'window';
function Person(name) {
  this.name = name;
}
 
var kim = Person('kim');
 
console.log(window.name); //kim

하지만 new 키워드를 빼먹는 순간 일반 함수 호출과 같아지기 때문에
이 경우는 this가 window에 바인딩된다.


명시적 this 바인딩 방법

call 메서드

메서드의 호출 주체인 함수를 즉시 실행하도록 하는 명령이다.
함수를 그냥 실행하면 this는 전역객체를 참조하지만
call메서드를 이용하면 임의의 객체를 this로 지정할 수 잇다.

var func = function ( a, b, c ){
	console.log( this , a , b , c );
};

func( 1, 2, 3 ); // window{...} 1 2 3 
func.call({ x : 1 }, 4 , 5, 6 ); // { x : 1 } 4 5 6

apply메서드

call메서드와 기능적으로 동일하지만 call메서드는 첫번째 인자를 배열로 받고
첫번째 인자를 제외한 나머지 모든 인자들을 호출할 함수 매개변수로 지정하는 반면,

apply메서드는 두번째 인자를 배열로 받아 그 배열의 요소들을 호출할 함수의 매개변수로 지정합니다. (여러개의 인수를 받는 메서드에게 하나의 배열로 인수들을 전달하고 싶을때 apply 메서드 사용)

call()은 인수 목록을 받고 apply()는 인수 배열을 받는다는 차이가 있다.

bind메서드

즉시 호출하지는 않고, this 및 인수들을 바탕으로 새로운 함수를 반환하기만 하는 메서드이다.
함수에 this를 미리 적용하는것, 그리고 부분 적용 함수를 구현하는 목적을 지닌다.


화살표 함수로 쓴 this

전역 컨텍스트에서 실행되더라도 this를 새로 정의하지 않고, 바로 외부 함수나 클래스의 this를 사용한다.

var Person = function (name, age) {
  this.name = name;
  this.age = age;
  this.say = function () {
    console.log(this); // Person {name: "Nana", age: 28}
 
    setTimeout(function () {
      console.log(this); // Window
      console.log(this.name + ' is ' + this.age + ' years old');
    }, 100);
  };
};
var me = new Person('Nana', 28);
 
me.say(); //global is undefined years old

위 코드를 보면 내부 함수에서 this가 전역 객체를 가리키는 바람에 의도와는 다른 결과가 나왔다.

var Person = function (name, age) {
  this.name = name;
  this.age = age;
  this.say = function () {
    console.log(this); // Person {name: "Nana", age: 28}
 
    setTimeout(() => {
      console.log(this); // Person {name: "Nana", age: 28}
      console.log(this.name + ' is ' + this.age + ' years old'); 
    }, 100);
  };
};
var me = new Person('Nana', 28); //Nana is 28 years old

하지만 화살표 함수로 바꾸면 제대로 된 결과가 나오는 걸 볼 수 있습니다.


정리

1. 전역공간에서의 this는 전역객체(window)를 참조한다.

2. 어떤 함수를 메서드로서 호출한 경우 this는 메서드 호출 주체(메서드명 앞의 객체)를 참조한다.

3. 어떤 함수를 함수로서 호출한 경우 this는 전역객체를 참조한다. (매서드 내부함수에서도 같다.)

4. 콜백 함수 내부에서 this는 해당 콜백 함수의 제어권을 넘겨받은 함수가 정의한 바에 따르며,

정의하지 않는 경우 전역객체를 참조한다.

5. 생성자 함수에서의 this는 생성될 인스턴스를 참조한다.

6. call, apply 메서드는 this를 명시적으로 지정하면서 함수 또는 메서드를 호출한다.

7. bind 메서드는 this 및 함수에 넘길 인수를 일부 지정해서 새로운 함수를 만든다.

참조자료

profile
90% of my problems magically disappeared when I slept well, ate well and went on regular walks

0개의 댓글