[JS] This 예약어

Pavel_Dmr·2022년 6월 24일
0

JavaScript

목록 보기
8/9

자바스크립트나 다른 언어를 다루다 보면 this라는 예약어을 사용하는 경우을 자주 보게 된다. 자바스크립트에서 this는 "누가 나를 불렀는가","이것"같은 뜻으로 해석 될 수있다.

this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 "자기참조변수(Self-Reference-Variable)이다.

this를 통해 자신이 속한 객체나 생성된 인스턴스의 프로퍼티나 메서드를 참조할 수있다.
this는 코드 어디서든 참조할 수 있다.

하지만 this는 객체의 프로퍼티나 메서드를 참조하기 위한 자기참조변수이므로, 통상적으로 객체의 메서드 내부나 생성자 함수 내부에서만 의미가 있다.

this가 가르키는 값은 함수 호출 방식에 따라 동적으로 바뀔 수 있다.

🍆 This 예약어 예제

단독 사용시

전역변수로 단독 사용시 global object를 가르킵니다.
브라우저에서 호출하는 경우에 [object Window]가 됩니다.
strict mode에서도 같습니다.

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

함수 내에서 사용시

전역에 선언된 함수 안에서 this는 지정되지않습니다. 지정되지 않은 경우, 자동으로 전역객체를 바라보기 때문에. window가 됩니다.

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

다만 strict mode에서는 함수 내의 this에 디폴트 바인딩이 없기 때문에.
타입 에러가 발생합니다.

메소드 안에서 사용시

메소드 호출 시 메소드 내부 코드에서 사용된 this는 해당 메소드를 호출한 객체로 바인딩됩니다.

	
var person = {
  firstName: '김',
  lastName: '상무',
  fullName: function () {
    return this.firstName + ' ' + this.lastName;
  },
};
 // person 객체에서 메소드 호출 정상적으로 나옴
person.fullName(); //"김 상무"

만약 콜백함수을 이용해서 호출 객체가 다른 객체면, call이나 apply 키워드로 호출 객체을 지정해서 this을 정상적으로 참조 할 수 있다.

var person = {
  firstName: "김",
  lastName: "상무",
  fullName: function () {
    return this.firstName + " " + this.lastName;
  },
};

function Get_Name(callback, obj) {
  console.log(callback()); //undefined 해당 메소드을 호출한 객체가 callback함수기때문에 this.firstName,lastName을 찾을수가 없다.
}

Get_Name(person.fullName, person);
var person = {
  firstName: "김",
  lastName: "상무",
  fullName: function () {
    return this.firstName + " " + this.lastName;
  },
};

function Get_Name(callback, obj) {
  //obj로 person 객체을 전달해주었기 때문에 this가 person 객체을 참조한다.
  console.log(callback.call(obj)); // 김 상무
}

Get_Name(person.fullName, person);

이벤트 핸들러에서 사용시

var btn = document.querySelector('#btn')
btn.addEventListener('click', function () {
  console.log(this); //#btn
});

이벤트 핸들러에서 this는 이벤트를 받는 HTML 요소를 가리킵니다.

생성자 안에서 사용시

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가 바인딩 됩니다.

명시적 바인딩 사용시

앞서 콜백함수처럼 this 바인딩이 제대로 되지 않을때, 객체을 직접 인자로 넘겨주고, 그 인자를 this로 만들어 주었는데, call()과 apply()는 명시적으로 바인딩을 하는데 도움이 된다.

function whoisThis() {
  console.log(this);
}
 
whoisThis(); //window
 
var obj = {
  x: 123,
};

//일반 함수 선언식임에도 call로 객체를 넘겨주었기 때문에 this가 var obj을 정상적으로 참조했다.
whoisThis.call(obj); //{x:123}
function Character(name, age) {
  this.name = name;
  this.age = age;
}
 
function Animal(name, age, race) {
    //this = Player가 되고 Character 함수의 내용만 빼온다 생각하면 된다.
  //call은 인자 목록을 , apply는 인자 배열을
  Character.call(this,name,age);
  Character.apply(this, [name, age]);
  this.race = race;
}
 
var me = new Animal('겨울이', 2, '사모예드');
console.log(me);

call은 인자 목록을, apply는 인수 배열을 받는 차이가 있다.

call() ,apply()는 보통 유사계열 객체에게 배열 메소드를 쓰고자 할때 사용합니다.

function func(a, b, c) {
  var args = Array.prototype.slice.apply(arguments);
  args.push('hi!');
  console.dir(args);
}
 
func(1, 2, 3); // [ 1, 2, 3, 'hi!' ]

arguments 객체는 함수에 전달된 인수를 Array 형태로 보여주지만, 함수 객체기 때문에 배열 메서드를 쓸수 없다. call또는 Apply로 this 역할을 할 인자를 전해주면 배열로 변환이 가능하다.

var list = {
  0: 'Kim',
  1: 'Lee',
  2: 'Park',
  length: 3,
};
 
Array.prototype.push.call(list, 'Choi');
console.log(list);

번외로 명시적으로 배열 컨트롤할 수 있지만, ES6부터 Array.from()이라는 메소드로 유사배열 객체를 복사해서,새 Array 객체로 만들수 있습니다.

var children = document.body.children; // HTMLCollection
 
children.forEach(function (el) {
  el.classList.add('on'); //ERROR! (children.forEach is not a function)
});

var children = document.body.children; // HTMLCollection
 
Array.from(children).forEach(function (el) {
  el.classList.add('on'); 
});

화살표(람다식) 함수 사용시

전역에서 함수 리터럴에서 this가 전역 객체가 되는게 싫다면, 내부에 화살표 함수로 작성하면 된다. 화살표 함수는 전역 컨텍스트에서 실행되더라도 this를 새로 정의하지 않고,바로 바깥 함수나 클래스의 this를 쓴다. 이는 보통 함수나 객체 정의시 프로그램이 사용자가 this나 arguments을 사용할 수 있도록 생성하기 때문인데, 화살표함수을 사용하면 생성하지 않기때문에, 자바스크립트에서 없는 변수나 객체을 찾는다면, 더 상위 스코프에서 찾아 호출하기때문에. 화살표함수 을 감싸고 있는 객체나 함수의 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
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
profile
노는게 좋아

0개의 댓글