객체 생성자
- 객체 생성자는 함수를 통해서 새로운 객체를 만들고 그 안에 넣고 싶은 값 혹은 함수들을 구현할 수 있게함
- 인스턴스가 초기화될 때 실행하는 생성자 함수
function Animal(type, name, sound) { // 생성자 constructor
this.type = type;
this.name = name;
this.sound = sound;
this.say = function() {
console.log(this.sound);
};
}
let dog = new Animal('개', '멍멍이', '멍멍') // 인스턴스 instance
let cat = new Animal('고양이', '야옹이', '야옹');
dog.say(); // 멍멍
cat.say(); // 야옹
- 객체 생성자를 사용할 때는 보통 함수의 이름을 대문자로 시작, 새로운 객체를 만들 때에는 new 키워드를 앞에 붙여줍니다
- 같은 객체 생성자 함수를 사용하는 경우, 특정 함수 또는 값을 재사용 할 수 있는데 바로 프로토타입입니다
프로토타입
- 모델의 청사진을 만들 때 쓰는 원형 객체(Orignial form)
- 프로토타입은 객체 생성자 함수 아래에 .prototype.[원하는키] = 코드를 입력하여 설정 가능
function Animal(type, name, sound) { // 생성자
this.type = type;
this.name = name;
this.sound = sound;
}
Animal.prototype.say = function() { // 프로토타입
console.log(this.sound);
};
Animal.prototype.shareValue = 1; // 프로토타입
let dog = new Animal('개', '멍멍이', '멍멍') // 인스턴트
let cat = new Animal('고양이', '야옹이', '야옹');
dog.say(); // 멍멍
cat.say(); // 야옹
console.log(dog.shareValue); // 1
console.log(cat.shareValue); // 1
__proto__, constructor, prototype의 관계
var Human = function(name) { // constructor
this.name = name;
}
Human.prototype.sleep = function() { // prototype
console.log('zzz')
};
var steve = new Human('steve'); // instance
결과 화면은 이렇게 나온다
steve.__proto__ === Human.prototype // true
steve.sleep() // zzz
이런 관계를 가지고 있는것을 알 수 있다.
그렇다면 아래와 같이 Human이라는 부모 객체와 Student라는 자식 객체가 있는 경우에 Student 프로토타입에서 .sleep을 사용하려면 어떻게 해야할까?
var Human = function(name) { // constructor
this.name = name;
}
Human.prototype.sleep = function() { // prototype
console.log("zzz")
};
var steve = new Human('steve'); // instance
var Student = function(name) { // constructor
}
Student.prototype.learn = function() { // prototype
console.log("배우는중..")
}
var john = new Student('john'); // instance
john.learn();
john.sleep();
# case 1
john을 Human.prototype에 직접 연결
john.__proto__ = Human.prototype
사용하지 말아야한다. __proto__는 참조하는 용도로만 사용해야 한다.
# case 2
Student 프로토타입에 Human 프로토타입을 직접 대입
Student.prototype = Human.prototype
Student.prototype.learn = function () {}
// same as Human.prototype.learn과 같다
Human 프로토타입에도 learn이 생기게 된다
# case 3
Student 프로토타입에 Human 프로토타입의 복사본을 대입
Student.prototype = Object.create(Human.prototype); // 추가한 코드
Student.prototype.learn = function () {}
위 코드와 같이 Student 프로토타입 위에 Human 프로토 타입의 복사본을 넣어주면 된다
Human 프로토 타입의 복사본을 Student 프로토타입 아래에 넣으면 Student 생성자가 Human 생성자를 가리키고 learn이 인식되지 않는다.
위와 같이 해주면 Student.prototype과 Student 생성자의 연결고리가 끊어지게 된다
Student.prototype = Object.create(Human.prototype);
Student.prototype.constructor = Student; // 추가한 코드
Student.prototype.learn = function () {}
위와 같이 코드를 추가해서 직접 연결을 시켜줘야한다
자바스크립트가 OOP를 기반으로 만들어지지 않았기 때문에 OOP와 비슷하게 구현하기 위해 에러가 생길때마다 다양한 방법들로 구현하는 방식들 중 하나라고 생각하면 된다 (조금 깔끔하지 못해 보일 수 있다)
하지만 위와 같이 하게되도 Student의 context가 만들어질 뿐 john의 인스턴스가 Human까지 올라가지 못한다
Human의 this값이 undefined가 된다
var Student = function(name) {
Human.call(this, name); // 추가한 코드
// Human.apply(this, arguments)로 써도 된다
}
위와 같이 Sudent constructor안에 this를 올려주는 call, apply 함수를 사용해야 한다
var Human = function(name) { // constructor
this.name = name;
}
Human.prototype.sleep = function() { // prototype
console.log("zzz")
};
var steve = new Human('steve'); // instance
var Student = function(name) { // constructor
}
Student.prototype = Object.create(Human.prototype); // 추가한 코드
Student.prototype.constructor = Student; // 추가한 코드
Student.prototype.learn = function() { // prototype
Human.call(this, name); // 추가한 코드
console.log("배우는중..")
}
var john = new Student('john'); // instance
john.learn(); // 배우는중..
john.sleep(); // zzz
위와 같이 코드를 추가해주면
steve instanceof Human === true;
john instanceof Student === true;
john instanceof Human === true;
잘 연결이 된것을 확인할 수 있다.
using class keyword
위 코드를 class를 사용해 아래 코드처럼 바꿀수도 있다
class Human {
constructor(name) {
this.name = name;
}
sleep() {
}
}
var steve = new Human('steve');
class Student extends Human {
constructor (name) { // 부모와 arguments가 같다면 생략가능
super(name); // 부모와 arguments가 같다면 생략가능
}
learn() {
}
}
var john = new Student('john');
john.learn();
john.sleep();
'Language > JavaScript' 카테고리의 다른 글
[JS] Iterable object, Array-like object (0) | 2021.06.23 |
---|---|
[JS] ES6 특징 (0) | 2021.06.22 |
[JS] OOP (0) | 2021.02.26 |
[JS] 구조 분해 (0) | 2021.02.25 |
[JS] 화살표함수 (0) | 2021.02.24 |
댓글