1. 프로토타입과 상속


짚고 넘어가야할 Javascript 특징은 다음과 같습니다.

  • Javascript에서 함수는 Javascript 내장 객체인 Function의 생성자로 생성된 객체입니다.
  • Javascript에서 상속은 생성자 함수의 프로토타입을 활용합니다.
  • Javascript에서 프로토타입은 다른 객체에 공유 프로퍼티를 제공하는 객체입니다.
  • 함수 객체만이 프로토타입을 가집니다.
    함수 객체만이 호출이 가능하고 다른 객체를 생성할 수 있기 때문입니다.
    ES6의 화살표 함수는 프로토타입을 가지지 않습니다.

 

함수는 공장으로, 프로토타입은 공장에서 생산된 제품의 명세로 간주할 수 있습니다.
new 키워드로 함수를 호출할 때마다 해당 제품의 주문이 들어가고 공장은 프로토타입에 지정된 방식으로 생산합니다.

// User 생성자 함수를 만듭니다.
function User(name, interests) {
  this.name = name;
  this.interests = interests;
}
User.prototype.greeting = function() {
  console.log('Hi, I\'m ' + this.name + '.');
}

// 생성자 객체를 역참조하고 있는 `constructor` 프로퍼티를 이용해 누가 객체를 생성했는지 확인할 수 있습니다.
console.log(User.constructor === Function); // true 출력 

// User 생성자 함수가 생성되면 프로토타입 객체를 가집니다.
// User 생성자 함수 안의 프로토타입 객체는 User 생성자 함수에 의해 생성되었음을 확인해볼 수 있습니다.
console.log(User.prototype.constructor === User); // true 출력 

// User 생성자 함수로 user 객체를 생성하면,
// user 객체는 User 생성자 함수의 프로토타입 객체를 참조하는 `__proto__` 프로퍼티를 가집니다.
// 해당 `__proto__` 프로퍼티는 프로토타입 체인에서 링크 역할을 담당합니다.
var user = new User();
console.log(user.__proto__ === User.prototype) // true 출력 
// User 생성자 함수를 만듭니다.
function User(name, interests) {
  this.name = name;
  this.interests = interests;
}
User.prototype.greeting = function() {
  console.log('Hi, I\'m ' + this.name + '.');
}

// User 생성자 함수의 .call() 메서드를 호출하는 형태는 자바에서 super()를 호출하는 것과 유사합니다.
// 한 가지 차이점은 call() 메서드의 첫 번째 인자는 객체여야 하며, 이 객체가 실행 컨텍스트의 역할을 합니다.
function TeamMember(name, interests, tasks) {
  User.call(this, name, interests);
  this.tasks = tasks;
}

// 하위 클래스는 상위 클래스를 확장합니다.
// TeamMember 생성자 함수에 의해 생성된 객체들은 User 프로토타입 객체의 프로퍼티를 가지고,
// 각 TeamMember의 객체는 TeamMember 프로토타입을 연결하는 __proto__ 프로퍼티를 가지게 됩니다.
TeamMember.prototype = Object.create(User.prototype);

// User 생성자 함수의 프로토타입 객체의 `greeting()` 메서드를 오버라이딩합니다.
TeamMember.prototype.greeting = function() {
  console.log('I\'m ' + this.name + '. Welcome to the team!');
};

TeamMember.prototype.work = function() {
  console.log('I\'m working on ' + this.tasks.length + ' tasks');
};

console.log(User.prototype === TeamMember.prototype); // false 출력
console.log(User.prototype.constructor === TeamMember.prototype.constructor); // true

2. 프로토타입 체인


[그림 1] prototype 객체와 prototype 체인을 통한 상속

위와 같은 상속(프로토타입 체인)을 아래와 같이 확인해볼 수 있습니다.

// 프로토타입 체인 확인하기
console.log(member.__proto__ === TeamMember.prototype); // true 출력
console.log(TeamMember.__proto__ === User.prototype);   // true 출력
console.log(User.__proto__ === Object.prototype);       // true 출력

// 위 방법보다 더 나은 방법
console.log( TeamMember.prototype.isPrototypeOf(member) );

따라서 __proto__ 프로퍼티는 정말 조심해서 사용해야 합니다.
실수로 __proto__ 프로퍼티를 다른 것으로 변경하면 상속이 깨지게 됩니다.

상속받지 않은(프로토타입 체인으로 거슬러 올라가지 않아도 되는) 자기 자신의 프로퍼티를 확인해보고 싶다면 아래의 방법을 사용합니다.

member.hasOwnProperty('name'); // true 출력
member.hasOwnProperty('move'); // false 출력

'Web > Javascript' 카테고리의 다른 글

[Javascript] select 박스에 이벤트 달기  (0) 2020.04.30
[Javascript/jQuery] .closest()  (0) 2020.04.03
[Javascript] DataTables  (0) 2020.04.02
[Javascript/jQuery] .find() 함수  (1) 2020.03.27
[Javascript] 비동기 처리와 콜백 함수  (1) 2020.03.06