OOP Javascript
객체 지향 프로그래밍, Javascript
기존의 Java, C++과 같은 클래스 기반의 객체지향 언어에서는 앞으로 생성할 객체의 기능과 구조는 선언된 클래스에서 결정이 되지만 자바스크립트에서는 객체 자체(super object;prototype object)로부터 상속을 받아 새로운 객체(sub object)를 생성하게 된다. 이러한 차이점들을 통해 javascript만의 특징을 알아본다.
생성자 함수
function Person(name){
this.name = name;
}
Person.prototype.introduce = function(){
return 'My name is ' + this.name;
}
var p1 = new Person('egoing');
document.write(p1.introduce()+"<br />");
var p2 = new Person('leezche');
document.write(p2.introduce());
객체를 생성할때 변수는 보통 생성자 함수내에서 선언을 하고 메소드는 prototype
을 사용해서 선언한다. prototype
을 사용해서 함수를 정의하는 것은 선언자를 통해 객체가 생성될 때마다 메모리라던지 성능상의 비효율을 가져오기 때문이다. 그리고 선언한 객체는 new
를 사용해서 생성하며 생성자함수는 일반함수와 구분하기위해 첫글자를 대문자로 표시하는 편이다.
class
ES6부터 포함된 개념으로 위에서 처럼 생성자 함수를 통해 객체를 생성하는것이 아니라 class 키워드를 통해 객체를 생성할 수 있다.
class Person{
constructor(name, first, second){
this.name = name;
this.first = first;
this.second = second;
}
sum(){
return 'sum : '+(this.first + this.second);
}
}
var kim = new Person('kim', 10, 20);
console.log('kim', kim);
class
로 객체를 생성할 때 초기화 하는 부분은 constructor
메소드로 선언하면 된다.
그리고 객체의 메소드를 구현할 때는 생성자함수에서 prototype
을 이용해서 선언하였으나 class
내에서 function 키워드없이 함수를 선언하면 된다.
상속, prototype
객체의 상속은 중복되는 코드를 삭제하고 연관된 하위 객체도 함께 수정이 용이하여 유지보수 측면에서도 용이하다. 우선 객체를 상속하기위해 객체의 원형을 의미하는 키워드prototype
를 이용하면 된다. prototype
에 저장된 속성들은 생성자를 통해서 객체가 만들어질 때 그 객체에 연결된다.
여러 단계로 상속을 반복하여 객체와 객체를 연결하는 prototype chain을 만들 수 있다.
function Person(name){
this.name = name;
}
Person.prototype.name=null;
Person.prototype.introduce = function(){
return 'My name is '+this.name;
}
function Programmer(name){
this.name = name;
}
Programmer.prototype = new Person();
Programmer.prototype.coding = function(){
return "hello world";
}
var p1 = new Programmer('egoing');
document.write(p1.introduce()+"<br />");
document.write(p1.coding()+"<br />");
여기서 주의해야할 점은 prototype chain으로 다른 객체를 상속받을 때 생성자를 사용해서 객체를 할당해서 상속받아야한다는 점이다. 예를 들면 자식객체.prototype = 부모객체.prototype
은 안된다. 항상 자식객체.prototype = new 부모객체();
이런식으로 사용해야 하위 객체에 변화가 생겨도 상위 객체에는 영향을 주지 않기 때문이다.
객체를 상속하는 방법1. proto 사용하기
그리고 추가로 객체를 상속하는 또다른 방법은 __proto__
를 사용하는 방법이 있다. 이 키워드를 사용하면 해당 객체를 바로 어느 객체의 자식을 만들어 proto link를 만들 수 있다. 매우 유연한 방법이지만 권장되는 방식은 아닌 것 같다.
var superObj = {superVal:'super'}
var subObj = {subVal:'sub'}
subObj.__proto__ = superObj;
console.log('subObj.subVal =>', subObj.subVal);
console.log('subObj.superVal =>', subObj.superVal);
subObj.superVal = 'sub';
console.log('superObj.superVal =>', superObj.superVal);
객체를 상속하는 방법2. Object.create 메소드 사용하기
var superObj = {superVal:'super'}
var subObj = Object.create(superObj);
subObj.subVal = 'sub';
class로 생성된 객체의 상속
추가로 class
를 이용해 객체를 생성하는 경우에는 아래와 같이 extends
키워드를 사용하여 상속을 진행한다. 그리고 상속받은 자식 클래스에서 부모 클래스로부터 상속받은 메소드를 변경하거나 추가할 때 super
키워드를 사용해서 부모 클래스에 접근할 수 있다. 아래의 코드에서 super()
는 부모클래스의 생성자를 의미한다.
class Person{
constructor(name, first, second) {
this.name = name;
this.first = first;
this.second = second;
}
sum(){
return this.first + this.second;
}
}
class PersonPlus extends Person{
constructor(name, first, second, third) {
super(name, first, second);
this.third = third;
}
avg(){
return (super.sum() + this.third) / 2;
}
}
var p = new PersonPlus('kim', 10, 20);
console.log(p.avg()); // 15
데이터 타입과 참조
javascript에서 데이터 타입은 크게 두가지로 분류한다.
원시 데이터
- 숫자
- 문자열
- 불리언(true/false)
- null
- undefined
그 외는 모두 객체이다.
원시 데이터 중에서 숫자, 문자열, 불리언은 래퍼객체(String, Number, Boolean)으로 싸여있어서 객체처럼 메소드를 사용할 수 있다. 하지만 해당 메소드를 사용할 때만 자바스크립트 내부에서 일시적으로 생성되는 것으로 실제 객체처럼 사용되는 것은 아니다.
이러한 두 데이터 타입의 가장 큰 차이는 변수에 할당되는 시점이다.
원시 데이터 타입은 아래와 같이 새로운 변수에 할당될 때 복사가 되지만
var a = 1;
var b = a;
b = 2;
console.log(a); // 결과:1
객체같은 경우에는 새로운 변수가 해당 객체를 참조하는 식으로 할당되기 때문에 원래의 객체에 영향을 준다.
var a = {'id':1};
var b = a;
b.id = 2;
console.log(a.id); // 결과: 2
[출처]