객체 지향 프로그래밍(생성자와 프로토타입)
생성자
자바와 동일한 생성자
new를 붙이고 함수처럼 호출
바로 자바스크립트 생성자(constructor) 함수
객체를 생성하는 함수를 생성자 함수라고 부름
다른 언어에서는 class가 있지만 자바스크립트에서는 없다
생성자 함수가 그 역할을 대신한다
사람 생성자를 만들면 다음과 같다
1 2 3 4 5 6 7 8 | function Person(name, gender) { this.name = name; this.gender = gender; this.sayHello = function() { alert(this.name + ' said "hello"'); } this.... // 사람의 속성과 메소드를 더 정의할 수 있습니다. } | cs |
new라는 키워드를 사용해서 호출
new 생성자(인자);
이렇게 하면 된다.
1 2 3 4 | var zero = new Person('Zero', 'm'); // Person {name: 'Zero', gender: 'm'} var hero = new Person('Hero', 'f'); // Person {name: 'Hero', gender: 'f'} zero.sayHello(); // 'Zero said "hello"' hero.sayHello(); // 'Hero said "hello"' | cs |
하나의 Person 생성자를 바탕으로 zero와 hero 두 사람 객체를 만들었다.
그리고 이 객체들은 공통적으로 sayHello라는 메소드를 갖고 있다.
1 2 3 4 5 6 7 | function Person(name, gender) { this.name = name; this.gender = gender; this.sayHello = function() { alert(this.name + ' said "hello"'); } } | cs |
Person 옆에 (name, gender)는 처음 만들 때 매개변수를 받는 부분임을 알 수 있다.
그렇게 받은 매개변수들을 this.name
, this.gender
에 저장
this는 바로 생성자 함수 자신을 가리킨다
이렇게 this에 저장된 것들은 new를 통해 객체를 만들 때 그 객체에 적용
프로토 타입
1 2 3 4 5 6 7 | function Person(name, gender) { this.name = name; this.gender = gender; } Person.prototype.sayHello = function() { alert(this.name + ' said "hello"'); }; | cs |
this.sayHello
대신에 Person.prototype
에 sayHello를 넣었다.
prototype 객체는 사전 그대로 원형을 뜻함
같은 생성자로부터 만들어진 객체들은 모두 이 원형 객체를 공유
따라서 Person의 prototype 객체에 sayHello라는 메소드를 넣으면 Person 생성자로 만든 모든 객체는 이 메소드 사용이 가능
그런데 this.sayHello
보다 prototype에 Person.prototype.sayHello
로 넣는 게 더 효율적
prototype은 모든 객체가 공유하고 있어서 한 번만 만들어지지만
this에 넣은 것은 객체 하나를 만들 때마다 메소드도 하나씩 만들어지기 때문에 불필요한 메모리 낭비가 발생
아예 메소드뿐만 아니라 속성까지 다 prototype에 넣기도 함
prototype과 __proto__
1 | new Person('Nero', 'm'); // Person {name: "Nero", gender: "m", __proto__: Object} | cs |
Nero라는 새 사람 객체를 만들었더니 그 안에 처음보는 __proto__라는 객체가 있다.
constructor과 우리가 추가한 sayHello 그리고 또다시 __proto__가 있다.
1 2 3 4 5 | { constructor: function Person(name, gender), sayHello: function() {}, __proto__: Object } | cs |
__proto__가 바로 실제 객체를 만들 때 생성자의 prototype이 참조된 모습
생성자의 prototype을 참조하기 때문에 __proto__와 prototype은 같다
아까 Person.prototype.sayHello
를 했던 것이 들어있는데
추가로 constructor(생성자)에 대한 정보까지 들어있다.
__proto__ 안에 __proto는 객체상속때 쓰는것 추후에 알아 사용해보자.
정리하면
- constructor는 생성자 함수 그 자체를 가리킴
- prototype은 생성자 함수에 정의한 모든 객체가 공유할 원형
- __proto__는 생성자 함수를 new로 호출할 때, 정의해두었던 prototype을 참조한 객체
- prototype은 생성자 함수에 사용자가 직접 넣는 거고, __proto__는 new를 호출할 때 prototype을 참조하여 자동으로 만들어짐
- 생성자에는 prototype, 생성자로부터 만들어진 객체에는 __proto__
- 따라서 사용자는 prototype만 신경쓰면 된다. __proto__는 prototype이 제대로 구현되었는지 확인용으로 사용한다.
prototype, __proto__와 constructor의 관계
또한 Person.prototype === (Person생성자로 만들어진 객체).__proto__;
이기 때문에
(Person생성자로 만들어진 객체).__proto__.constructor === Person;
도 성립한다.
상속의 필요성
1 2 3 4 5 6 7 | function Vehicle(name, speed) { this.name = name; this.speed = speed; } Vehicle.prototype.drive = function () { console.log(this.name + ' runs at ' + this.speed) }; | cs |
이렇게 Vehicle 생성자 만들고 drive 메소드로 달릴 수 있는데
근데 drive 메소드 하나밖에 없으니 좀 그러니
boost라는 메소드를 만들어서 최고 속도로 달릴 수 있는 기능을 추가하면 괜찮을 거 같아서
Vehicle.prototype.boost = function () {...}
이렇게 추가하자니
한 가지가 걸린다.
Vehicle 안에는 트럭, SUV, 스포츠카, 세단 등 많은데 트럭이 boost하는 건 좀 이상하지 않나?
이럴 때 상속이 필요
상속은 외국에서 확장(extend)이라고도 표현
즉 부모 생성자의 기능을 물려받는 동시에 새로운 기능을 추가할 수도 있다.
출처 : https://www.zerocho.com/category/JavaScript/post/573c2acf91575c17008ad2fc