비록 다른 객체지향적인 언어들과의 차이점에 대한 논쟁들이 있긴 하지만, JavaScript는 강력한 객체지향 프로그래밍 능력들을 지니고 있다.
이 글에서는 객체지향 프로그래밍에 대해 소개하는 것으로 시작해서 자바스크립트의 객체 모델, 그리고 자바스크립트에서의 객체지향 프로그래밍 개념에 대해 간단한 예제로 살펴볼 것이다.
자바스크립트 리뷰(JavaScript review)
만약 변수, 형, 함수, 스코프 등 자바스크립트의 개념에 대해 명확히 이해하고 있지 못하다면, A re-introduction to JavaScript 를 참고해 보자. Core JavaScript 1.5 Guide 라는 글도 도움이 될 것이다.
객체지향 프로그래밍(Object-oriented programming)
객체지향 프로그래밍은 실제 세계에 기반한 모델을 만들기 위해 추상화를 사용하는 프로그래밍 패러다임이다. 객체지향 프로그래밍은 modularity, polymorphism, encapsulation 을 포함하여 이전에 정립된 패러다임들부터 여러가지 테크닉들을 사용한다. 오늘날, 많은 유명한 프로그래밍 언어(자바, 자바스크립트, C#, C++, 파이썬, PHP, 루비, 오브젝트C)는 객체지향 프로그래밍을 지원한다.
객체지향 프로그래밍은 함수들의 집합 혹은 단순한 컴퓨터의 명령어들의 목록 이라는 기존의 프로그래밍에 대한 전통적인 관점에 반하여, 관계성있는 객체들의 집합이라는 관점으로 접근하는 소프트웨어 디자인으로 볼 수 있다. 객체지향 프로그래밍에서, 각 객체는 메시지를 받을 수도 있고, 데이터를 처리할 수도 있으며, 또다른 객체에게 메시지를 전달할 수도 있다. 각 객체는 별도의 역할이나 책임을 갖는 작은 독립적인 기계로 볼 수 있는 것이다.
객체지향 프로그래밍은 보다 유연하고 유지보수성이 높은 프로그래밍을 하도록 의도되었고, 대규모 소프트웨어 공학에서 널리 알려져 있다. 객체지향 프로그래밍이 갖는 modularity 에 기반한 강력한 힘에 의해, 객체지향적인 코드는 개발을 보다 단순하게 했고, 시간이 흐른 뒤에도 보다 쉽게 이해할 수 있도록 했으며, 복잡한 상황이나 절차들을 덜 모듈화된 프로그래밍 방법들보다 더 직접적으로 분석하고, 코딩하고, 이해할 수 있도록 만들었다.2
용어(Terminology)
- Class
- 객체의 특성을 정의
- Object
- Class의 인스턴스
- Property
- 객체의 특성(예: 색깔)
- Method
- 객체의 능력(예: 걷기)
- Constructor
- 인스턴스와 되는 시점에서 호출되는 메서드
- Inheritance
- 클래스는 다른 클래스로부터 특성들을 상속받을 수 있다.
- Encapsulation
- 클래스는 해당 객체의 특성들만을 정의할 수 있고, 메서드는 그 메서드가 어떻게 실행되는지만 정의할 수 있다. (외부 접근 불가)
- Abstraction
- 복잡한 상속, 메서드, 객체의 속성의 결합은 반드시 현실 세계를 시뮬레이션할 수 있어야 한다.
- Polymorphism
- 다른 클래스들이 같은 메서드나 속성으로 정의될 수 있다.
객체지향 프로그래밍에 대한 보다 확장된 설명은 Object-oriented programming 를 참고하면 된다.
프로토타입기반 프로그래밍(Prototype-based programming)
프로토타입 기반 프로그래밍은 클래스가 존재하지 않는 객체지향 프로그래밍의 한가지 스타일로, 동작 재사용(behavior reuse, 클래스기반 언어에서는 상속이라고함)은 프로토타입으로서 존재하는 객체를 데코레이팅하는 과정을 통해 수행된다.
프로토타입 기반 언어의 원형적인 예는 David Ungar과 Randall Smith가 개발한 'Self'라는 프로그래밍 언어이다. 그러나 클래스가 없는 프로그래밍 스타일이 최근 인기를 얻으며 성장하였고, 자바스크립트, Cecil, NewtonScript, Io, MOO, REBOL, Kevo, Squeak 등의 언어에서 채택되어 왔다.2
자바스크립트 객체지향 프로그래밍(JavaScript Object Oriented Programming)
Core Objects
자바스크립트는 코어(core)에 몇 개의 객체를 갖고 있다. 예를들면, Math, Object, Array, String과 같은 객체가 있다. 아래의 예제는 Math 객체를 사용해서 무작위 숫자를 만들어내는 것을 보여준다.
alert(Math.random());
자바스크립트의 core object들의 리스트는 Core JavaScript 1.5 Reference:Global Objects 라는 글을 참고하면 자세히 알 수 있다.
자바스크립트의 모든 객체는 Object 객체의 인스턴스이므로 Object의 모든 속성과 메서드를 상속받는다.
Custom Objects
The Class
class문을 흔하게 볼 수 있는 C++이나 자바와는 달리 자바스크립트는 class문이 포함되지 않은 프로토타입 기반 언어이다. 이로인해 때때로 class 기반 언어에 익숙한 프로그래머들은 혼란을 일으킨다. 자바스크립트에서는 function을 class로서 사용한다. 클래스를 정의하는 것은 function을 정의하는 것만큼 쉽다. 아래 예제에서는 Person 이라는 이름의 클래스를 새로 정의하고 있다.
function Person() { }
The Object (Class Instance)
obj 이름의 객체의 새로운 인스턴스를 만들때에는 new obj 라는 statement를 사용하고, 차후에 접근할 수 있도록 변수에 결과를 받는다.
아래의 예제에서 Person이라는 이름의 클래스를 정의한 후에, 두개의 인스턴스를 생성하고 있다.
function Person() { } var person1 = new Person(); var person2 = new Person();
The Constructor
생성자는 인스턴스화되는 순간((객체 인스턴스가 생성되는 순간) 호출된다. 생성자는 해당 클래스의 메서드이다. 자바스크립트에서는 함수 자체가 그 객체의 생성자 역할을 하기 때문에 특별히 생성자 메서드를 정의할 필요가 없다. 클래스 안에 선언된 모든 내역은 인스턴스화되는 그 시간에 실행된다.생성자는 주로 객체의 속성을 설정하거나 사용하기 위해 객체를 준비시키는 메서드를 호출할 때 주로 사용된다. 클래스 메서드를 추가하고 정의하는 것은 나중에 설명한다.
function Person() { alert('Person instantiated'); } var person1 = new Person(); var person2 = new Person();
The Property (object attribute)
function Person(gender) { this.gender = gender; alert('Person instantiated'); } var person1 = new Person('Male'); var person2 = new Person('Female'); //display the person1 gender alert('person1 is a ' + person1.gender); // person1 is a Male
The methods
메서드는 앞서 살펴본 속성과 같은 방식을 따른다. 차이점이 있다면 메서드는 function 이기 때문에 function 형태로 정의된다는 것입니다. 메서드를 호출하는 것은 속성에 접근하는 것과 매우 유사한데 단지 끝에 () 를 추가하면 된다. argument가 있다면 괄호 안에 입력해준다. 메서드를 정의하기 위해서는 클래스의 prototype에 명명된 속성에 함수를 할당하면 된다. 이때 할당된 이름은 해당 객체의 메서드를 호출할 때 사용되는 이름이다.
아래의 예에서는 Person 클래스에 sayHello() 라는 메서드를 정의하고 사용하고 있다.
function Person(gender) { this.gender = gender; alert('Person instantiated'); } Person.prototype.sayHello = function() { alert ('hello'); }; var person1 = new Person('Male'); var person2 = new Person('Female'); // call the Person sayHello method. person1.sayHello(); // hello
자바스크립트에서 메서드는 "컨텍스트에 관계없이" 호출될 수 있는 속성으로서 클래스/객체에 연결되어 있다. 다음 예제의 코드를 살펴보자.
function Person(gender) { this.gender = gender; } Person.prototype.sayGender = function() { alert(this.gender); }; var person1 = new Person('Male'); var genderTeller = person1.sayGender; person1.sayGender(); // alerts 'Male' genderTeller(); // alerts undefined alert(genderTeller === person1.sayGender); // alerts true alert(genderTeller === Person.prototype.sayGender); // alerts true
genderTeller.call(person1); //alerts 'Male'
Inheritance
상속은 하나 이상의 클래스를 특별한 버전의 클래스로 생성하는 하나의 방법이다. (다만 자바스크립트는 오직 하나의 클래스를 상속받는 것만 지원한다.) 이 특별한 클래스는 흔히 자식 클래스(child)라고 불리우고 원본 클래스는 흔히 부모 클래스(parent)라고 불리운다. 자바스크립트에서는 부모 클래스의 인스턴스를 자식 클래스에 할당함으로써 상속이 이루어진다. 최신 브라우저에서는 Object.create 메서드를 사용해서 상속을 수행할 수도 있다.
Core JavaScript 1.5 Reference:Global Objects:Object:prototype 에 나와있는 설명과 같이 자바스크립트는 자식 클래스의 prototype.constructor 를 검색하지 않으므로 직접 명시해주어야 한다.
// define the Person Class function Person() {} Person.prototype.walk = function(){ alert ('I am walking!'); }; Person.prototype.sayHello = function(){ alert ('hello'); }; // define the Student class function Student() { // Call the parent constructor Person.call(this); } // inherit Person Student.prototype = new Person(); // correct the constructor pointer because it points to Person Student.prototype.constructor = Student; // replace the sayHello method Student.prototype.sayHello = function(){ alert('hi, I am a student'); } // add sayGoodBye method Student.prototype.sayGoodBye = function(){ alert('goodBye'); } var student1 = new Student(); student1.sayHello(); student1.walk(); student1.sayGoodBye(); // check inheritance alert(student1 instanceof Person); // true alert(student1 instanceof Student); // true
Object.create 를 사용하면 상속을 아래와 같이 수행할 수 있다.
Student.prototype = Object.create(
Person.prototype);
Encapsulation
In the previous example, Student
does not need to know how the Person
class's walk()
method is implemented, but still can use that method; the Student
class doesn't need to explicitly define that method unless we want to change it. This is called encapsulation, by which every class inherits the methods of its parent and only needs to define things it wishes to change.
Abstraction
Abstraction is a mechanism that permits modeling the current part of the working problem. This can be achieved by inheritance (specialization), or composition. JavaScript achieves specialization by inheritance, and composition by letting instances of classes be the values of attributes of other objects.
The JavaScript Function class inherits from the Object class (this demonstrates specialization of the model). and the Function.prototype property is an instance of Object (this demonstrates composition)
var foo = function(){}; alert( 'foo is a Function: ' + (foo instanceof Function) ); alert( 'foo.prototype is an Object: ' + (foo.prototype instanceof Object) );
Polymorphism
Just like all methods and properties are defined inside the prototype property, different classes can define methods with the same name; methods are scoped to the class in which they're defined. This is only true when the two classes do not hold a parent-child relation (when one does not inherit from the other in a chain of inheritance).
Notes
The techniques presented in this article to implement object-oriented programming are not the only ones that can be used in JavaScript, which is very flexible in terms of how object-oriented programming can be performed.
Similarly, the techniques shown here do not use any language hacks, nor do they mimic other languages' object theory implementations.
There are other techniques that make even more advanced object-oriented programming in JavaScript, but those are beyond the scope of this introductory article.
References
- Mozilla. "Core JavaScript 1.5 Guide", http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide
- Wikipedia. "Object-oriented programming", http://en.wikipedia.org/wiki/Object-...ed_programming
Original Document Information
- Author(s): Fernando Trasviña <f_trasvina at hotmail dot com>
- Copyright Information: © 1998-2005 by individual mozilla.org contributors; content available under a Creative Commons license
Es: https://developer.mozilla.org/es/docs/Introducción_a_JavaScript_orientado_a_objetos