
인사이드 자바스크립트를 공부하며 정리하는 포스팅입니다.
1.클래스, 생성자, 메서드
일반적으로 C++, Java와 같은 언어에서는 class라는 키워드를 제공하여 프로그래머가 클래스를 만들 수 있다.
그리고 클래스와 같은 이름의 메서드로 생성자를 구현한다. 그러나 자바스크립트에는 이러한 개념이 없다.(ES5에서는)
자바스크립트에서는 함수객체로 클래스, 생성자, 메서드도 구현 가능하다.
var Person = function(arg){
this.name = arg;
};
Person.prototype.getName = function(){
return this.name;
}
Person.prototype.setName = function(name){
this.name = name;
}
var me = new Person("song");
console.log(me.getName());
2.상속
자바스크립트는 클래스를 기반으로 하는 전통적인 상속을 지원하지는 않는다.(ES5기준) 하지만 자바스크립트 특성 중 객체 프로토타입 체인을 이용하여 상속을 구현할 수 있다.
1) 클래스 개념 없이 객체의 프로토타입으로 상속 구현하기.
아래 예제는 더글라스 크락포드가 자바스크립트 객체를 상속하는 방법으로 소개한 코드이다.
var create_object = function(o){
function F() {}
F.prototype = o;
return new F();
};
생성된 F객체는 object o에 프로토타입 링크가 연결되어 있고,
또, 이 object o는 Object prototype에 프로토타입 링크가 연결되어 있다.
그리고 프로토타입으로 상속을 구현하기에 중심이되는 또 다른 메서드가 있다.
바로 extend() 메서드이다. 자바스크립트에서는 범용적으로 extend() 메서드로 자신이 원하는 객체 혹은 함수를 추가시킨다.
다음 코드는 jQuery 1.0의 extend 함수이다.
function extend(obj, prop){
if(!prop){prop = obj; obj = this;}
for(var i in prop) obj[i] = prop[i];
return obj;
}
위와 같은 extend() 함수의 약점은 얕은 복사를 하고 있다는 것이다. 프로퍼티 중 객체가 있는 경우 깊은 복사를 하는 것이 일반적이다.
create_object(), extend() 메서드를 이용하여 상속을 하는 예제를 구현해 보자.
//클래스 개념 없이 프로토타입 특성으로만 상속 구현하기
//더글라스 크락포드가 자바스크립트 객체를 상속하는 방법으로 소개한 코드.
var create_object = function(o){
function F() {}
F.prototype = o;
return new F();
};
// _proto_ _proto_
//F ------> object o -------> Object.prototype
var person = {
name : "song",
getName : function(){
return this.name;
},
setName : function(arg){
this.name = arg;
}
};
var student = create_object(person);
student.setName("ssong");
console.log(student.getName());
//위와 같이 부모 객체의 메서드를 그대로 상속받아서 사용할 수 있고, 자신의 메서드를 재정의 혹은 추가로 구현할 수 있다.
//이때, 자바스크립트에서는 범용적으로 extend()라는 이름의 함수로 자산이 원하는 객체 혹은 메서드를 추가한다.
function extend(obj, prop){
if(!prop){prop = obj; obj = this;}
for(var i in prop) obj[i] = prop[i];
return obj;
}
var studentAdded = {
setAge : function(age){
this.age = age;
},
getAge : function(){
return this.age;
}
};
extend(student, studentAdded);
student.setAge(25);
console.log(student.getAge());
//한 단계 더 상속을 구현해보도록 하겠다.
//student를 상속받은 HiSchoolStudent를 구현하겠다.
var hiSchoolStudent = create_object(student);
var hiSchoolStudentAdded = {
grade : 3,
setGrade : function(grade){
this.grade = grade;
},
getGrade : function(){
return this.grade;
}
};
extend(hiSchoolStudent, hiSchoolStudentAdded);
console.log(hiSchoolStudent.getName());
console.log(hiSchoolStudent.getAge());
console.log(hiSchoolStudent.getGrade());
2) 클래스역할을 하는 함수로 상속하기.
아래 예제는 일반적인 상속 예제이다.
핵심이 되는 부분은 Student.prototype에 부모가 될 Person의 인스턴스를 넣어주고, 생성자를 다시 지정해주는 것이다.
이렇게 함으로써, Student의 객체는 Person 객체의 함수와 메서드를 사용할 수 있게 프로토타입 링크가 형성된다.
주의할 점은 자동으로 부모 객체의 생성자가 호출되지는 않으므로 자식 생성자에서 부모 생성자를 호출해주어야 한다.
Person.call(this, name); 부분이 부모 생성자를 호출해 주는 부분이다.
부모 생성자에 생성될 객체를 this로 넘긴다.
//클래스역할을 하는 함수로 상속하기
var Person = function(name){
this.name = name;
};
Person.prototype.setName = function(name){
this.name = name;
};
Person.prototype.getName = function(){
return this.name;
};
var Student = function(name, _calss){
//부모클래스 생성자 호출
Person.call(this, name);
this.class = _calss;
};
Student.prototype = new Person();
Student.prototype.constructor = Student;
Student.prototype.getClass = function(){
return this.class;
};
Student.prototype.setClass = function(_calss){
this.class = _calss;
};
var song = new Student("song", 3);
console.log(song.getName());
console.log(song.getClass());
console.log(song instanceof Person); // true
console.log(song instanceof Student); // true
3.캡슐화
자바스크립트의 강력한 특성 중 하나인 클로저를 활용하여 캡슐화를 할 수 있다.
1) 기본 예제
아래 예제는 public 메서드가 클로저 역할을하고, private 멤버인 name에 접근한다.
자바스크립트에서 할 수 있는 기본적인 정보은닉 방법이다.
*모듈 패턴
주의할 점은 private 멤버가 객체나 배열인 경우 사용자가 get~~()함수를 통해 받은 값을 손쉽게 수정할 수 있다. 때문에 깊은 복사를 통해서 새로은 객체나 배열을 리턴해주어야 한다.
var Person = function(arg){
var name = arg ? arg: "song";
return {
getName: function(){
return name;
},
setName: function(arg){
name = arg;
}
};
}
var song = Person(); // or var song = new Person();
console.log(song.getName());
위 예제는 객체를 리턴하는데, 이 객체는 Person 함수 객체의 프로토타입에는 접근할 수 없다.
때문에 Person을 부모로 하는 프로토타입을 이용한 상속을 구현하기에는 용이하지 않다. 때문에 이를 보완하기 위해 함수를 반환한다.
2) 캡슐화를 적용한 상속가능 함수.
var Person = function(arg){
var name = arg ? arg: "song";
var Person = function(){}
Person.prototype = {
getName: function(){
return name;
},
setName: function(arg){
name = arg;
}
};
return Person;
}();
var song = new Person();
console.log(song.getName());