[JavaScript] prototype, this, class

vgotu99·2024년 10월 15일

생성자 함수와 prototype

function User(first, last) {
  this.firstName = first
  this.lastName = last
}

User.prototype.getFullName = function () {
  return `${this.firstName} ${this.lastName}`
}

const peter = new User('Peter', 'Parker')
const tom = new User('Tom', 'Holland')
const andrew = new User('Andrew', 'Garfield')
const tobey = new User('Tobey', 'Maguire')

console.log(peter)
// user {firstName: 'Peter', lastName: 'Parker'}
// firstName : "Peter"
// lastName : "Parker"
// [[Prototype]] : Object
// getFullName :  ƒ ()
console.log(peter.getFullName())
// Peter Parker

/*
peter가 아닌 tom, andrew, tobey 와 같은 다른 객체 형태의 데이터는
User 생성자 함수의 prototype에 있는 getFullName 함수를 참조하여 method로 이용하므로 메모리 관리에 용이하다.
*/

User 생성자 함수에 getFullName 함수를 prototype에 추가하게 되면, 각 객체(peter, tom, andrew, tobey)가 getFullName을 개별적으로 복사하지 않고, 공통된 메모리 공간을 참조하여 사용하게 된다.
객체마다 동일한 함수를 새로 생성하지 않으므로 메모리 효율성 측면에서 유리하다.

this

this는 함수 내부에서 호출될 때의 객체를 참조하는 키워드이다. 다만 어떤 함수어디서 호출되었는지에 따라 다른 대상을 가리킨다.

왜 굳이 this를 왜 쓰나요?

후술되긴 하겠지만 this를 사용하면 동적인 값에 맞게 함수를 재사용하며 대응할 수 있고 객체 내부의 구조나 이름이 변경되더라도 정상 동작하므로 효율적으로 유지보수할 수 있다. 또한 this를 사용하면 내부 데이터가 외부에 노출되지 않도록 캡슐화할 수 있다.

// * 일반 함수와 화살표 함수에서의 this

// 일반 함수에서 정의되는 경우
const peter = {
  name: 'Peter',
  normalFunc: function () {
    console.log(this.name)
  },
  arrowFunc: () => {
  	console.log(this.name)
  },
}

peter.normalFunc() // Peter
peter.arrowFunc() // undefined

// ===================================

// 화살표 함수에서 정의되는 경우
const timer = {
  name: 'Peter',
  normalTimeout: function () {
    setTimeout(function() {
      console.log(this.name)
    }, 1000);
  },
  arrowTimeout: function () {
    setTimeout(() => {
      console.log(this.name)
    }, 1000);
  }
}

timer.normalTimeout() // undefined
timer.arrowTimeout() // Peter

일반 함수

일반 함수에서 this는 호출 위치에서 정의된다. 즉, 함수를 호출한 객체를 가리킨다.
동적인 값이 호출되는 경우 this와 일반 함수를 사용하여 대응할 수 있다.

화살표 함수

화살표 함수에서 this는 자신이 선언된 함수 범위에서 정의된다. 즉, 자신이 선언된 함수의 this를 그대로 상속받아 사용한다.
콜백 함수나 비동기 함수 내에서 this가 의도치 않게 바뀌지 않도록 할 때 사용하며 특히 setTimeout, setInterval에서 자주 사용된다.

Class

기본 문법

// class를 이용한 기존 prototype 코드 리팩토링
/*
function User(first, last) {
  this.firstName = first
  this.lastName = last
}

User.prototype.getFullName = function () {
  return `${this.firstName} ${this.lastName}`
}
*/
class User {
  constructor (first, last) {
    this.firstName = first
    this.lastName = last
  }
  getFullName() {
    return `${this.firstName} ${this.lastName}`
  }
}

const peter = new User('Peter', 'Parker')
const tom = new User('Tom', 'Holland')
const andrew = new User('Andrew', 'Garfield')
const tobey = new User('Tobey', 'Maguire')

확장(상속)

class Vehicle {
  constructor(name, wheel) {
    this.name = name
    this.wheel = wheel
  }
}

const vehicle = new Vehicle('운송수단', 2)

// 확장(상속)
class Car extends Vehicle {
  constructor(name, wheel, hasLicense) {
    super(name, wheel)
    this.hasLicense = hasLicense
  }
}

const myCar = new Car('현대', 4, true)

클래스 상속을 사용하여 클래스를 다른 클래스로 확장할 수 있다. 즉, 기존에 존재하던 클래스의 기능을 토대로 새로운 기능을 추가한 클래스를 만들 수 있다.

0개의 댓글