💡 다형성 (polymorphism)
: 프로그램 언어의 다형성(polymorphism)은 그 프로그래밍 언어의 자료형 체계의 성질을 나타내는 것으로, 프로그램 언어의 각 요소들(상수, 변수, 식, 오브젝트, 함수, 메소드 등)이 다양한 자료형(type)에 속하는 것이 허가되는 성질을 가리킨다. 반댓말은 단형성(monomorphism)으로, 프로그램 언어의 각 요소가 한가지 형태만 가지는 성질을 가리킨다.
-> 다형성 체계를 가진 언어에서는, StringValue와 같은 범용 메소드 이름을 정의하여 형태에 따라 각각 적절한 변환 방식을 정의해둠으로써 객체의 종류와 상관없는 추상도가 높은 변환 형식을 구현할 수 있다.
/* 단형성 체계 */
//숫자를 문자열로 바꾸는 경우
string = StringFromNumber(number);
//날짜를 문자열로 바꾸는 경우
string = StringFromDate(date);
/* 다형성 체계 */
//숫자를 문자열로 바꾸는 경우
string = number.StringValue();
//날짜를 문자열로 바꾸는 경우
string = date.StringValue();
💡 응집력과 결합력
function User(name, age) {
this.name = name;
this.age = age;
this.sayName = function() {
console.log(this.name);
};
}
const user1 = new User("Lee", 20);
console.log(user1); // User {name: "Lee", age: 20, sayName: function (), constructor: Object}
user1.sayName(); // Lee
부모와 자식이 있다고 가정했을 때, 부모는 자식을 위한 돈을 금고에 넣어두고 자식이 사용할 수 있도록 하였다.
이 예시에서의 금고가 프로토타입을 의미한다.
금고는 들고 다니는 것이 아닌 멀리 위치해 있는 보관용 상자이다.
따라서 금고(프로토타입)을 사용하여 메모리 누수를 줄일 수 있다.
부모는 조부모의, 조부모는 그 위의 부모의 돈을 금고에서 꺼내 체인처럼 연결하여 사용한다.
이것이 바로 프로토타입 체인이다. 프로토타입 체인은 최상위 객체(전역 객체)까지 이어져있다.
전역객체의 프로토타입에도 원하는 값이 없다면 참조 에러가 발생한다.
✍️ Prototype
function User(name, age) {
this.name = name;
this.age = age;
}
User.prototype.sayName = function() {
console.log(this.name);
};
const user1 = new User("Lee", 20);
console.log(user1); // User {name: "Lee", age: 20, sayName: function (), constructor: Object}
user1.sayName(); // Lee
관점의 차이이다.
부모 입장에서 금고는 자식에게 줄 금고이다.
자식 입장에서 부모의 금고는 부모에게서 받은 금고이다.
prototype
과 __proto__
를 나누는 이유는 시간이 흘러 자식 또한 자식을 낳아 상속을 시켜줘야 하기 위해 상속 받은 prototype과 상속 해주는 prototype의 구분이 필요하기 때문이다.
prototype
__proto__
자바스크립트는 클래스 기반 객체지향 프로그래밍 언어가 아닌 프로토타입 기반의 객체지향 프로그래밍 언어이다.
자바스크립트의 class
는 기존 프로토타입 기반 패턴의 syntactic sugar(문법적 설탕)이라 볼 수 있다.
💡 클래스 사용
class
키워드 사용constructor
생성자 메소드를 클래스 안에서 정의하여 해당 클래스로 인스턴스(객체)를 생성시 초기화할 값들을 정의한다.extends
키워드를 사용하여 클래스간 상속이 가능하다.super
키워드를 사용하여 부모 클래스의 constructor
생성자 메서드를 호출하거나 부모 클래스의 프로퍼티를 참조할 수 있다.✍️ Class
class Parent {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayName() {
console.log(this.name);
}
}
const parent = new Parent("Chulsu", 40);
console.log(parent); // User {name: "Chulsu", age: 40, sayName: function (), constructor: Object}
parent.sayName(); // Chulsu
class Children extends Parent {
constructor(name, age, gender) {
super(name, age);
this.gender = gender;
}
}
const child = new Children("Gildong", 2, "male");
console.log(child); // Children {name: "Gildong", age: 2, gender: "male", constructor: Object}
child.sayName(); // Gildong
prototype
을 설정하기 위한 모던한 방법이 있다.
바로 Object.create
메소드를 사용해서 객체를 생성하는 방법이다.
Object.create(prototype)
Object.create
메서드의 인자로 Object.create
메서드가 호출되어 생성될 객체의 __proto__
가 될 Prototype
을 입력한다.Object.getPrototypeOf(obj)
Object.getPrototypeOf
메서드의 인자로 입력된 객체의 prototype
을 리턴한다.Object.setPrototypeOf(obj, prototype)
Object.setPrototypeOf
메서드의 첫번째 인자로 입력한 객체의 프로토 타입을 다른 객체 또는 null 로 설정할 수 있다.Object.setPrototypeOf
메서드의 첫번째 인자로 입력한 객체에 두번째 인자를 prototype
으로 추가해준다.✍️ Object.create()
function Iphone() {
this.applePay = true;
}
const proto = {
canIUseApplePay: function() {
console.log(this.applePay);
}
};
const iphone = new Iphone();
Object.setPrototypeOf(iphone, proto);
iphone.canIUseApplePay(); // true
function IphoneInKorea() {
this.applePay = false;
}
IphoneInKorea.prototype = Object.create(proto);
const iphoneInKorea = new IphoneInKorea();
iphoneInKorea.canIUseApplePay(); // false