어제에 이어 객체 지향 프로그래밍에대한 포스팅의 연장이다.
클래스라는 문법이 ES6에서 추가되었기 때문에
과거에 이용했었던 방법을 알면 클래스의 작동 방식을
어느정도 알 수 있다.
오늘은 그에대한 포스팅이다.
클래스가 없었을때에는 어떻게 객체 지향 프로그래밍을 했을까?
var Car = function(position) {
var someInstance = {}; // 함수를 실행했을 때 담아줄 객체
someInstance.position = position; // position값의 초기화 부분
someInstance.move = function() { // 메소드 추가
this.position += 1;
// this.position === someInstance.position
}
return someInstance; // 함수 실행 결과 출력
};
var car1 = Car(5) // position 초기값은 5
car1.move() // move 메소드 실행
console.log(car1.position) //output 6
이런식으로 만들면 함수를 재사용해서 클래스처럼 쓸 수 있다.
여기에 또다른 자동차를 만드려면 var car2 = Car()
을 쓰면 될 것이다.
이렇게보면 클래스를 만드는것과 똑같이 보인다.
위 방식 말고도 다른 방식이 또 있는데
바로 Object.create
를 이용하는 방법이다.
var someMethods = {}; // 메소드를 담아줄 객체
someMethods.move = function() {
this.position += 1;
};
var Car = function(position) {
var someInstance = Object.create(someMethods);
someInstance.position = position;
return someInstance;
};
var car1 = Car(5);
car1.move()
console.log(car1.position) // output 6
여기서 Object.create
의 역활은 무엇일까?
MDN에서 살펴보면 지정된 프로토타입 객체 및 속성을 갖는
새 객체를 만든다고 되어있다.
위의 예제에서 두번째 줄에 // 함수를 실행했을 때 담아줄 객체
라고 주석을 달아놓았는데 Object.create
가 그 역활을 하는것이다.
여기서 또하나 의문이 드는데 프로토타입이 무엇이냐는 것이다.
이제 여기서 오늘의 주제인 prototype
에 대해 알아보자
ES6 이전에 객체 지향 프로그래밍에서 클래스를 만드는 방법중
그나마 간결한 방법이 있다.
var Car = function(position) {
this.position = position;
};
Car.prototype.move = function() {
this.position += 1;
};
var car1 = new Car(5);
car1.move()
console.log(car1.position) // output 6
이렇게 프로토타입을 이용하면 더 간결하게 만들 수 있다.
이렇게 선언한 함수로 객체를 만들때에는 new
를 붙여줘야한다.
이는 현제 사용되는 클래스로 선언한 객체를 만들때에도 동일하다.
이상태에서 부모의 객체를 상속받는 방법은 아래와 같다.
var Car = function(position) {
this.position = position;
};
Car.prototype.move = function() {
this.position += 1;
};
var Minicar = function() {
Car.call(this, position) // Car.apply(this, arguments)
}
var car1 = new Car(5);
car1.move()
console.log(car1.position) // output 6
이제 prototype
에 대해 자세히 살펴보자
prototype
은 쉽게 생각해서 상위객체라고 보면 된다.
function Human(name) {
this.name = name;
}
let steve = new Human('steve')
steve.__proto__
위와 같이 입력하면
이렇게 나오는걸 볼 수 있는데 여기서 생성자인 constructor
을 누르면
steve
는 Human
의 자손으로 들어가 있는걸 알 수 있다.
그렇기 때문에
steve.__proto__ === Human.prototype
// output true
이렇게 나온다
여기서 한층 더 들어가게 되면
steve.__proto__.__proto__ === Object.prototype
// output true
Object
와 동일하다고 볼 수 있는데
이렇게 연결되어있는 관계를 프로토타입 체인이라고 한다.
프로토타입 체인으로 연결되어있기 때문에
steve
에는 선언하지 않았던 toStiring()
이 사용이 가능하다.
steve.toString()
// output "[object Object]"
toString()
메소드는 Object
에 내장되어있는 메소드이다.
정리를 해보면
Human은 steve의 생성자 constructor
이며
__proto__
는 객체에서 접근하는 인스턴스 확인 방법이고
prototype
은 constructor
함수에서 접근하는 인스턴스 확인 방법이다.
때문에 Object
가 가지고 있는 속성은 Human
도 가지고 있고
steve
는 Object
와 Human
의 속성을 모두 가지고 있는 형태로 보여진다.
그래서 억지로 steve
에 toString()
이 사용이 가능한 것이다.
프로토타입을 이용해 유사배열을 만드는 것도 가능하다.
let MyArray = function() {}
MyArray.prototype = Array.prototype;
let myarr = new MyArray();
myarr.push(1);
console.log(myarr)
// output MyArray [1]
prototype
이 어떤방식으로 작동되는지 알아보았는데
조금은 복잡할수도 있겠지만 쉽게 생각해보면
그렇게 어려운것도 아닌것 같다.
이 글은 어제 썼던 객체 지향 프로그래밍 글과
함께 보면 좋을것 같아 링크로 남겨두었다.