From 149b599368b4e27cf7d05f270a43519f599372fd Mon Sep 17 00:00:00 2001 From: MDN Date: Tue, 18 Jan 2022 00:57:02 +0000 Subject: [CRON] sync translated content --- .../objects/classes_in_javascript/index.html | 395 +++++++++++++++++++++ .../javascript/objects/inheritance/index.html | 394 -------------------- .../objects/object-oriented_js/index.html | 287 --------------- 3 files changed, 395 insertions(+), 681 deletions(-) create mode 100644 files/ko/learn/javascript/objects/classes_in_javascript/index.html delete mode 100644 files/ko/learn/javascript/objects/inheritance/index.html delete mode 100644 files/ko/learn/javascript/objects/object-oriented_js/index.html (limited to 'files/ko/learn/javascript/objects') diff --git a/files/ko/learn/javascript/objects/classes_in_javascript/index.html b/files/ko/learn/javascript/objects/classes_in_javascript/index.html new file mode 100644 index 0000000000..0549a416ef --- /dev/null +++ b/files/ko/learn/javascript/objects/classes_in_javascript/index.html @@ -0,0 +1,395 @@ +--- +title: Inheritance in JavaScript +slug: Learn/JavaScript/Objects/Classes_in_JavaScript +translation_of: Learn/JavaScript/Objects/Inheritance +original_slug: Learn/JavaScript/Objects/Inheritance +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}
+ +

OOJS에 대한 온갖 잡지식을 설명했으니, 이 글에서는 부모 클래스에서 자식 클래스를 상속하는 방법을 알아봅니다. 덤으로 OOJS를 구현하는데 몇 가지 참고사항도 있습니다.

+ + + + + + + + + + + + +
선수조건:컴퓨터 기본지식, HTML과 CSS에 대한 기본적인 이해,자바스크립트에 어느 정도 익숙할 것 (see First steps and Building blocks).  OOJS 기초 지식 (see Introduction to objects).
학습목표:Javascript에서 상속을 구현하는 법을 이해합니다.
+ +

프로토타입 상속

+ +

지금까지 몇 가지 상속을 살펴보았습니다 — 프로토타입 체인이 어떻게 동작하는지, 체인을 통해 멤버들을 탐색하는 것도 보았죠. 하지만 이는 대부분 브라우저가 알아서 처리하는 로직이었습니다. 그러면 우리가 직접 객체를 생성하고 상속하려면 어떻게 해야 할까요?

+ +

실질적인 예제를 통해 알아보도록 합시다.

+ +

시작하기

+ +

먼저 oojs-class-inheritance-start.html를 다운 받으시고 (running live 페이지도 보시구요). 파일 내에서 이전 예제에서 계속 봐 왔던 Person() 생성자를 보실 수 있습니다 — 생성자에 속성 몇 개를 정의했기에 조금 다릅니다:

+ +
function Person(first, last, age, gender, interests) {
+  this.name = {
+    first,
+    last
+  };
+  this.age = age;
+  this.gender = gender;
+  this.interests = interests;
+};
+ +

메소드는 전부 아래처럼 prototype에 정의되어 있습니다:

+ +
Person.prototype.greeting = function() {
+  alert('Hi! I\'m ' + this.name.first + '.');
+};
+ +
+

Note: 소스 코드에는 bio()와 farewell()메소드가 정의되어 있습니다. 잠시 후에 다른 생성자로 어떻게 상속하는지 알아보도록 합시다.

+
+ +

객체 지향에 대해 처음 정의할 때 언급했었던 Teacher 클래스를 만들어 봅시다. Person을 상속받고 아래 몇 가지를 추가해서요:

+ +
    +
  1. subject 속성 — 교사가 가르치는 과목을 나타냅니다.
  2. +
  3. 기존의 greeting() 보다 조금 더 공손한 인사를 하는 메소드  — 교사가 학생들에게 건넬 만한 표현으로 하죠.
  4. +
+ +

Teacher() 생성자 함수 정의

+ +

제일 처음 단계에서는 Teacher() 생성자를 만들어야 합니다 — 기존 코드 밑에 아래 코드를 추가하세요:

+ +
function Teacher(first, last, age, gender, interests, subject) {
+  Person.call(this, first, last, age, gender, interests);
+
+  this.subject = subject;
+}
+ +

Person() 생성자와 여러모로 비슷해 보이지만 여지껏 보지 못했던 한가지 차이점이 있습니다 — call() 함수죠. call() 함수의 첫번째 매개변수는 다른 곳에서 정의된 함수를 현재 컨텍스트에서 실행할 수 있도록 합니다. 실행하고자 하는 함수의 첫 번째 매개변수로 this를 전달하고 나머지는 실제 함수 실행에 필요한 인자들을 전달하면 됩니다.

+ +

Teacher()의 생성자는 Person()을 상속받았으므로 같은 매개변수들이 필요합니다. 따라서 동일한 매개변수들을 call()의 인자로 전달하여 실행합니다.

+ +

마지막 줄에서는 새 속성인 subject를 정의하여 Person이 아닌 Teacher만이 갖는 속성을 만들어 줍니다.

+ +

참고로 아래와 같이 할 수도 있습니다:

+ +
function Teacher(first, last, age, gender, interests, subject) {
+  this.name = {
+    first,
+    last
+  };
+  this.age = age;
+  this.gender = gender;
+  this.interests = interests;
+  this.subject = subject;
+}
+ +

다만 이는 Person()을 상속받은게 아니라 단지 동일한 인자를 정의했을 뿐이죠. 이건 원하는 방법이 아닐 뿐더러 코드의 길이만 더 늘어났습니다.

+ +

매개변수가 없는 생성자 상속하기

+ +

상속하려는 생성자가 속성을 매개변수로 받지 않는다면 call()의 매개변수에도 아무것도 전달할 필요가 없습니다. 아래처럼 간단한 생성자가 있다면:

+ +
function Brick() {
+  this.width = 10;
+  this.height = 20;
+}
+ +

widthheight 속성을 상속받기 위해 아래처럼만 하면 됩니다(물론 이후 설명할 방법을 써도 되구요):

+ +
function BlueGlassBrick() {
+  Brick.call(this);
+
+  this.opacity = 0.5;
+  this.color = 'blue';
+}
+ +

call() 함수에 this만 넘긴 것을 보세요. — Brick() 생성자에서 매개변수를 통해 초기화 하는 속성들이 없으므로 call()에도 넘길 필요가 없습니다.

+ +

Teacher()의 프로토타입과 생성자 참조 설정하기

+ +

다 좋은데 문제가 있습니다. 방금 정의한 새 생성자에는 생성자 함수 자신에 대한 참조만 가지고 있는 프로토타입 속성이 할당되어 있습니다. 정작 상속 받은 Person() 생성자의 prototype 속성은 없죠. Javascript 콘솔에서 Object.getOwnPropertyNames(Teacher.prototype)을 쳐서 확인해 보세요. 다음엔 TeacherPerson으로 바꿔서 확인해 보세요. Teacher()생성자는 Person()의 메소드를 상속받지 못하였습니다. Person.prototype.greetingTeacher.prototype.greeting 구문을 실행하여 비교해 보세요. Teacher()가 메소드도 상속 받으려면 어떻게 해야 할까요?

+ +
    +
  1. 기존 코드에 아래 코드를 추가하세요: +
    Teacher.prototype = Object.create(Person.prototype);
    + 구원 투수 create()의 등판입니다.  새 객체를 생성하여 Teacher.prototype으로 할당했죠. 새 객체는 Person.prototype 객체를 자신의 프로토타입으로 가지고 있으므로 Person.prototype에 정의된 모든 메소드를 사용할 수 있습니다.
  2. +
  3. 넘어가기 전에 한가지 더 해야 합니다. 마지막 줄을 추가하고 나면 Teacher.prototypeconstructor 속성이 Person()으로 되어 있습니다. Teacher.prototype에 Person.prototype을 상속받은 객체를 할당했기 때문이죠. 코드를 저장한 뒤 브라우저로 불러와서 Teacher.prototype.constructor 구문의 반환 값을 확인해 보세요.
  4. +
  5. 문제의 소지가 있으므로 고쳐야 됩니다. 소스에 아래 코드를 추가하세요: +
    Teacher.prototype.constructor = Teacher;
    +
  6. +
  7. 저장하고 다시 브라우저에서 불러오면 의도한대로 Teacher.prototype.constructorTeacher()를 반환합니다. 게다가 Person()도 상속받았죠!
  8. +
+ +

Teacher()에 새 greeting() 함수 부여하기

+ +

Teacher()에 새로운 greeting() 함수를 정의하여 코드를 완성합시다.

+ +

가장 간단한 방법은 Teacher()의 프로토타입에 정의합니다. — 아래 코드를 추가하세요:

+ +
Teacher.prototype.greeting = function() {
+  var prefix;
+
+  if (this.gender === 'male' || this.gender === 'Male' || this.gender === 'm' || this.gender === 'M') {
+    prefix = 'Mr.';
+  } else if (this.gender === 'female' || this.gender === 'Female' || this.gender === 'f' || this.gender === 'F') {
+    prefix = 'Mrs.';
+  } else {
+    prefix = 'Mx.';
+  }
+
+  alert('Hello. My name is ' + prefix + ' ' + this.name.last + ', and I teach ' + this.subject + '.');
+};
+ +

조건문을 이용해서 성별에 따라 적절한 호칭이 붙은 교사의 인삿말을 alert 창으로 띄웁니다.

+ +

예제 사용해 보기

+ +

소스를 환성했으니 아래 코드를 통해 새 Teacher() 인스턴스를 생성해 봅시다(아니면 인자를 원하는 값으로 변경하시거나요):

+ +
var teacher1 = new Teacher('Dave', 'Griffiths', 31, 'male', ['football', 'cookery'], 'mathematics');
+ +

저장한 코드를 다시 불러와서 아래처럼 teacher1의 속성과 메소드를 확인해 봅시다:

+ +
teacher1.name.first;
+teacher1.interests[0];
+teacher1.bio();
+teacher1.subject;
+teacher1.greeting();
+teacher1.farewell();
+ +

아주 잘 실행될 겁니다. 1, 2, 3, 6 줄은 Person() 생성자(클래스)에서 상속 받은 멤버에 접근합니다. 4번째 줄은 Teacher() 생성자(클래스)만 가지고 있는 멤버에 접근합니다. 5번째 줄은 Person()에서 상속 받은 멤버도 있지만 Teacher()가 이미 자신만의 새 메소드를 정의했으므로 Teacher()의 메소드에 접근합니다.

+ +
+

Note: 코드가 잘 동작하지 않으면 완성된 버전을 확인해 보세요. (실행 페이지도 보시구요).

+
+ +

이 테크닉이 Javascript에서 상속 받는 클래스를 만드는 유일한 방법은 아니지만 잘 동작하며 상속을 구현하는 방법을 잘 설명하고 있습니다.

+ +

조금 더 명확한 방식으로 Javascript에서 상속을 구현하는 새 {{glossary("ECMAScript")}} 기능도 관심 가질만한 주제입니다(Classes 참조). 아직까지 많은 브라우저에서 지원하지 못하고 있기 때문에 여기서 다를 주제는 아닙니다. 여러 문서에서 제시한 코드들은 IE9보다 더 오래된 구형 브라우저에서도 사용 가능하며 더 이전 버전을 지원하기 위한 방법들도 있습니다. 

+ +

JavaScript 라이브러리를 쓰면 간단합니다 — 상속 기능을 사용하기 위한 보편적인 방법이죠. 예를들어 CoffeeScriptclassextends등의 기능을 제공합니다.

+ +

더 연습하기

+ +

OOP theory section, 에서는 개념적으로 Person을 상속받고 Teacher보다 덜 공손한 greeting() 메소드를 재정의한 Student 클래스를 정의했었습니다. 해당 절에서 Student의 인삿말이 어땠는지 확인해 보시고 Person()을 상속받는 Student() 생성자를 구현해 보세요. greeting() 함수도 재정의 해 보시구요.

+ +
+

Note: 코드가 잘 동작하지 않으면 완성된 버전 을 확인해 보세요.(실행 페이지도 보시구요).

+
+ +

객체 멤버 요약

+ +

요약하면, 상속에 있어 고려해야 할 세 가지 유형의 속성/메소드가 있습니다:

+ +
    +
  1. 생성자 함수 내에서 인스턴스에 정의하는 유형. 직접 작성한 코드에서는 생성자 함수 내에 this.x = x 구문과 유사하게 정의되어 있으므로 발견하기 쉽습니다. 브라우저 내장 코드에서는 객체 인스턴스(보통 new 키워드를 통해 생성, ex) var myInstance = new myConstructor())에서만 접근할 수 있는 멤버입니다.
  2. +
  3. 생성자에 직접 정의하는 유형, 생성자에서만 사용 가능합니다. 브라우저 내장 객체에서 흔히 사용하는 방식인데, 인스턴스가 아니라 생성자 함수에서 바로 호출되는 유형입니다. Object.key() 같은 함수들이죠.
  4. +
  5. 인스턴스와 자식 클래스에 상속하기 위해 생성자의 프로토타입에 정의하는 유형. 생성자의 프로토타이비 속성에 정의되는 모든 멤버를 의미합니다. ex) myConstructor.prototype.x().
  6. +
+ +

뭐가 뭔지 헷갈려도 걱정하지 마세요 — 배우는 중이니 차츰 익숙해질겁니다.

+ +

ECMAScript 2015 클래스

+ +

ECMAScript 2015에서는 C++나 Java와 유사한 클래스 문법을 공개하여 클래스를 조금 더 쉽고 명확하게 재활용 할 수 있게 되었습니다. 이 절에서는 프로토타입 상속으로 작성한 Person과 Teacher 예제를 클래스 문법으로 변경하고 어떻게 동작하는지 설명하겠습니다.

+ +
+

Note: 대부분의 최신 브라우저에서 새로운 클래스 작성 방식을 지원합니다만 일부 구형 브라우저(Internet Explorer가 대표적)에서는 동작하지 않으므로 하위호환성을 위해 프로토타입 상속을 배워둘 필요가 있습니다.

+
+ +

Class-스타일로 재작성한 Person 예제를 보시죠:

+ +
class Person {
+  constructor(first, last, age, gender, interests) {
+    this.name = {
+      first,
+      last
+    };
+    this.age = age;
+    this.gender = gender;
+    this.interests = interests;
+  }
+
+  greeting() {
+    console.log(`Hi! I'm ${this.name.first}`);
+  };
+
+  farewell() {
+    console.log(`${this.name.first} has left the building. Bye for now!`);
+  };
+}
+ +

class 구문은 새로운 클래스를 작성함을 의미합니다. Class 블록 내에서 모든 기능을 정의할 수 있습니다.

+ + + + + +

이제 위에서 했듯이 new 연산자로 객체 인스턴스를 생성할 수 있습니다:

+ +
let han = new Person('Han', 'Solo', 25, 'male', ['Smuggling']);
+han.greeting();
+// Hi! I'm Han
+
+let leia = new Person('Leia', 'Organa', 19, 'female' ['Government']);
+leia.farewell();
+// Leia has left the building. Bye for now
+ +
+

Note: 코드를 까보면 class 부분은 프로토타입 상속으로 변환이 됩니다. — 문법 설탕(syntactic sugar)의 일종인거죠. 하지만 읽기 쉽다는데 대부분 동의하실 겁니다.

+
+ +

class 문법으로 상속

+ +

위에서 사람을 나타내는 클래스를 만들었습니다. Person 클래스는 일반적인 사람이 가질 만한 특성들을 나열하고 있죠; 이 절에서는 Person을 class 문법으로 상속받아 Teacher 클래스를 만들 예정입니다. 이 작업을 하위 클래스 생성이라 부릅니다.

+ +

하위 클래스를 만드려면 Javascript에서 extends 키워드를 통해 상속 받을 클래스를 명시합니다.

+ +
class Teacher extends Person {
+  constructor(first, last, age, gender, interests, subject, grade) {
+    this.name = {
+      first,
+      last
+    };
+
+  this.age = age;
+  this.gender = gender;
+  this.interests = interests;
+  // subject and grade are specific to Teacher
+  this.subject = subject;
+  this.grade = grade;
+  }
+}
+ +

constructor()에서 첫번쨰로 super() 연산자를 정의하면 코드를 조금 더 읽기 쉬워집니다. 이는 상위 클래스의 생성자를 호출하며 super()의 매개변수를 통해 상위 클래스의 멤버를 상속받을 수 있는 코드입니다.

+ +
class Teacher extends Person {
+  constructor(first, last, age, gender, interests, subject, grade) {
+    super(first, last, age, gender, interests);
+
+    // subject and grade are specific to Teacher
+    this.subject = subject;
+    this.grade = grade;
+  }
+}
+ +

Teacher의 인스턴스를 생성하면 의도한대로 이제 TeacherPerson 양 쪽의 메소드와 속성을 사용할 수 있습니다.

+ +
let snape = new Teacher('Severus', 'Snape', 58, 'male', ['Potions'], 'Dark arts', 5);
+snape.greeting(); // Hi! I'm Severus.
+snape.farewell(); // Severus has left the building. Bye for now.
+snape.age // 58
+snape.subject; // Dark arts
+ +

Person을 수정하지 않고 Teacher를 생성한 것처럼 또 다른 하위클래스도 생성할 수 있습니다.

+ +
+

Note: GitHub에서 es2015-class-inheritance.html 예제를 참조하세요(실행 페이지).

+
+ +

Getters와 Setters

+ +

생성한 클래스 인스턴스의 속성 값을 변경하거나 최종 값을 예측할 수 없는 경우가 있을 겁니다. Teacher 예제를 보면 인스턴스를 생성하기 전에는 어떤 과목을 가르칠지 아직 모릅니다. 학기 도중에 가르치는 과목이 변경될 수도 있구요.

+ +

이런 상황에 getter/setter가 필요합니다.

+ +

Teacher 클래스에 getter/setter를 추가해 봅시다. 마지막에 작성했던 예제를 그대로 사용해보죠.

+ +

Getter와 setter는 쌍으로 동작합니다. Getter가 현재 값을 반환한다면 그에 대응하는 setter는 해당하는 값을 변경합니다.

+ +

수정된 Teacher 클래스는 아래와 같습니다:

+ +
class Teacher extends Person {
+  constructor(first, last, age, gender, interests, subject, grade) {
+    super(first, last, age, gender, interests);
+    // subject and grade are specific to Teacher
+    this._subject = subject;
+    this.grade = grade;
+  }
+
+  get subject() {
+    return this._subject;
+  }
+
+  set subject(newSubject) {
+    this._subject = newSubject;
+  }
+}
+ +

위 클래스를 보시면 subject 속성에 대해 getter와 setter가 생겼습니다. 멤버 변수에는 _를 붙여 getter/setter와 구분을 하였습니다. 이렇게 하지 않으면 get/set을 호출할때마다 에러가 발생합니다:

+ + + +

두 기능이 실제로 어떻게 작동하는지 아래를 참조하세요:

+ +
// Check the default value
+console.log(snape._subject) // Returns "Dark arts"
+
+// Change the value
+snape._subject="Balloon animals" // Sets subject to "Balloon animals"
+
+// Check it again and see if it matches the new value
+console.log(snape._subject) // Returns "Balloon animals"
+ +
+

Note: GitHub에서 es2015-getters-setters.html 예제를 참조하세요(실행 페이지).

+
+ +

JavaScript에서 언제 상속을 사용해야 할까?

+ +

이 마지막 문서를 읽고 나면 "뭐가 이리 어렵냐"고 생각하실지도 모르겠습니다. 어렵긴 합니다 프로토타입과 상속은 Javascript에서 가장 난해한 부분이거든요. 하지만 이 부분은 Javascript가 강력하고 유연한 언어로써 작용할 수 있는 원동력이기에 충분한 시간을 들여 배울 가치가 있습니다.

+ +

어찌보면 여러분은 항상 상속하고 있었습니다. Web API나 브라우저 내장 객체인 string, array 등의 메소드/속성을 사용하면서 암묵적으로 상속을 사용하고 있었던거죠.

+ +

처음 시작하거나 작은 프로젝트에서 직접 상속을 구현하는 코드를 작성하는 경우는 그리 많지 않습니다. 필요하지도 않는데 상속을 위한 코드를 구현하는 건 시간 낭비에 불과하죠. 하지만 코드량이 많아질수록 상속이 필요한 경우가 생깁니다. 동일한 기능을 가진 클래스가 많아졌음을 발견했다면 기능들을 한데 묶어 공유할 수 있도록 일반 객체를 만들고 특이 객체들에게 상속하는 방식이 훨씬 편하고 유용하다는 점을 알 수 있습니다.

+ +
+

Note: Javascript에서는 프로토타입을 통해 상속이 구현되어 있어 이 방식을 흔히 위임이라고 표현합니다. 특이 객체들이 일반 객체에게 일부 기능의 실행을 위임하는 것이죠.

+
+ +

상속을 구현할때 상속 레벨을 너무 깊게 하지 말고, 메소드와 속성들이 정확히 어디에 구현되어 있는지 항상 인지해야 합니다. 브라우저 내장 객체의 prototype 역시 일시적으로 수정이 가능하지만 정말로 필요한 경우를 제외하고는 건드리지 말아야 합니다. 너무 깊은 상속은 디버그 할 때 끝없는 혼돈과 고통만을 줄 겁니다.

+ +

궁극적으로 객체는 함수나 반복문과 같이 고유한 역할과 장점을 지닌 채 코드를 재사용하는 또 다른 방법입니다. 서로 연관된 변수와 함수들을 하나로 묶어 다룰 필요가 있을때 객체가 좋은 아이디어입니다. 한 곳에서 다른 곳으로 데이터 집합을 전달할 때에도 객체가 유용합니다. 두가지 모두 생성자나 상속 없이도 가능한 일입니다. 딱 하나의 인스턴스만 필요할 경우 객체를 선언하지 않고 객체 리터럴만으로도 충분합니다. 당연히 상속은 필요없구요.

+ +

요약

+ +

이 글에서는 여러분들이 반드시 알아야 할 OOJS 이론과 문법의 나머지 부분에 대해 다루고 있습니다. 이 시점에서 여러분은 javascript 객체와 OOP 기초, 프로토타입과 프로토타입 상속, 클래스(생성자)를 만들고 인스턴스를 생성하며 기능을 추가하고, 다른 클래스를 상속 받아 하위 클래스를 만드는 방법을 배웠습니다.

+ +

다음 글에서는 Javascript 객체로 데이터를 교환하는 방식인 Javascript Object Notation(JSON)에 대해 알아봅시다.

+ +

See also

+ + + +

{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}

+ + + +

In this module

+ + diff --git a/files/ko/learn/javascript/objects/inheritance/index.html b/files/ko/learn/javascript/objects/inheritance/index.html deleted file mode 100644 index 72a2302d15..0000000000 --- a/files/ko/learn/javascript/objects/inheritance/index.html +++ /dev/null @@ -1,394 +0,0 @@ ---- -title: Inheritance in JavaScript -slug: Learn/JavaScript/Objects/Inheritance -translation_of: Learn/JavaScript/Objects/Inheritance ---- -
{{LearnSidebar}}
- -
{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}
- -

OOJS에 대한 온갖 잡지식을 설명했으니, 이 글에서는 부모 클래스에서 자식 클래스를 상속하는 방법을 알아봅니다. 덤으로 OOJS를 구현하는데 몇 가지 참고사항도 있습니다.

- - - - - - - - - - - - -
선수조건:컴퓨터 기본지식, HTML과 CSS에 대한 기본적인 이해,자바스크립트에 어느 정도 익숙할 것 (see First steps and Building blocks).  OOJS 기초 지식 (see Introduction to objects).
학습목표:Javascript에서 상속을 구현하는 법을 이해합니다.
- -

프로토타입 상속

- -

지금까지 몇 가지 상속을 살펴보았습니다 — 프로토타입 체인이 어떻게 동작하는지, 체인을 통해 멤버들을 탐색하는 것도 보았죠. 하지만 이는 대부분 브라우저가 알아서 처리하는 로직이었습니다. 그러면 우리가 직접 객체를 생성하고 상속하려면 어떻게 해야 할까요?

- -

실질적인 예제를 통해 알아보도록 합시다.

- -

시작하기

- -

먼저 oojs-class-inheritance-start.html를 다운 받으시고 (running live 페이지도 보시구요). 파일 내에서 이전 예제에서 계속 봐 왔던 Person() 생성자를 보실 수 있습니다 — 생성자에 속성 몇 개를 정의했기에 조금 다릅니다:

- -
function Person(first, last, age, gender, interests) {
-  this.name = {
-    first,
-    last
-  };
-  this.age = age;
-  this.gender = gender;
-  this.interests = interests;
-};
- -

메소드는 전부 아래처럼 prototype에 정의되어 있습니다:

- -
Person.prototype.greeting = function() {
-  alert('Hi! I\'m ' + this.name.first + '.');
-};
- -
-

Note: 소스 코드에는 bio()와 farewell()메소드가 정의되어 있습니다. 잠시 후에 다른 생성자로 어떻게 상속하는지 알아보도록 합시다.

-
- -

객체 지향에 대해 처음 정의할 때 언급했었던 Teacher 클래스를 만들어 봅시다. Person을 상속받고 아래 몇 가지를 추가해서요:

- -
    -
  1. subject 속성 — 교사가 가르치는 과목을 나타냅니다.
  2. -
  3. 기존의 greeting() 보다 조금 더 공손한 인사를 하는 메소드  — 교사가 학생들에게 건넬 만한 표현으로 하죠.
  4. -
- -

Teacher() 생성자 함수 정의

- -

제일 처음 단계에서는 Teacher() 생성자를 만들어야 합니다 — 기존 코드 밑에 아래 코드를 추가하세요:

- -
function Teacher(first, last, age, gender, interests, subject) {
-  Person.call(this, first, last, age, gender, interests);
-
-  this.subject = subject;
-}
- -

Person() 생성자와 여러모로 비슷해 보이지만 여지껏 보지 못했던 한가지 차이점이 있습니다 — call() 함수죠. call() 함수의 첫번째 매개변수는 다른 곳에서 정의된 함수를 현재 컨텍스트에서 실행할 수 있도록 합니다. 실행하고자 하는 함수의 첫 번째 매개변수로 this를 전달하고 나머지는 실제 함수 실행에 필요한 인자들을 전달하면 됩니다.

- -

Teacher()의 생성자는 Person()을 상속받았으므로 같은 매개변수들이 필요합니다. 따라서 동일한 매개변수들을 call()의 인자로 전달하여 실행합니다.

- -

마지막 줄에서는 새 속성인 subject를 정의하여 Person이 아닌 Teacher만이 갖는 속성을 만들어 줍니다.

- -

참고로 아래와 같이 할 수도 있습니다:

- -
function Teacher(first, last, age, gender, interests, subject) {
-  this.name = {
-    first,
-    last
-  };
-  this.age = age;
-  this.gender = gender;
-  this.interests = interests;
-  this.subject = subject;
-}
- -

다만 이는 Person()을 상속받은게 아니라 단지 동일한 인자를 정의했을 뿐이죠. 이건 원하는 방법이 아닐 뿐더러 코드의 길이만 더 늘어났습니다.

- -

매개변수가 없는 생성자 상속하기

- -

상속하려는 생성자가 속성을 매개변수로 받지 않는다면 call()의 매개변수에도 아무것도 전달할 필요가 없습니다. 아래처럼 간단한 생성자가 있다면:

- -
function Brick() {
-  this.width = 10;
-  this.height = 20;
-}
- -

widthheight 속성을 상속받기 위해 아래처럼만 하면 됩니다(물론 이후 설명할 방법을 써도 되구요):

- -
function BlueGlassBrick() {
-  Brick.call(this);
-
-  this.opacity = 0.5;
-  this.color = 'blue';
-}
- -

call() 함수에 this만 넘긴 것을 보세요. — Brick() 생성자에서 매개변수를 통해 초기화 하는 속성들이 없으므로 call()에도 넘길 필요가 없습니다.

- -

Teacher()의 프로토타입과 생성자 참조 설정하기

- -

다 좋은데 문제가 있습니다. 방금 정의한 새 생성자에는 생성자 함수 자신에 대한 참조만 가지고 있는 프로토타입 속성이 할당되어 있습니다. 정작 상속 받은 Person() 생성자의 prototype 속성은 없죠. Javascript 콘솔에서 Object.getOwnPropertyNames(Teacher.prototype)을 쳐서 확인해 보세요. 다음엔 TeacherPerson으로 바꿔서 확인해 보세요. Teacher()생성자는 Person()의 메소드를 상속받지 못하였습니다. Person.prototype.greetingTeacher.prototype.greeting 구문을 실행하여 비교해 보세요. Teacher()가 메소드도 상속 받으려면 어떻게 해야 할까요?

- -
    -
  1. 기존 코드에 아래 코드를 추가하세요: -
    Teacher.prototype = Object.create(Person.prototype);
    - 구원 투수 create()의 등판입니다.  새 객체를 생성하여 Teacher.prototype으로 할당했죠. 새 객체는 Person.prototype 객체를 자신의 프로토타입으로 가지고 있으므로 Person.prototype에 정의된 모든 메소드를 사용할 수 있습니다.
  2. -
  3. 넘어가기 전에 한가지 더 해야 합니다. 마지막 줄을 추가하고 나면 Teacher.prototypeconstructor 속성이 Person()으로 되어 있습니다. Teacher.prototype에 Person.prototype을 상속받은 객체를 할당했기 때문이죠. 코드를 저장한 뒤 브라우저로 불러와서 Teacher.prototype.constructor 구문의 반환 값을 확인해 보세요.
  4. -
  5. 문제의 소지가 있으므로 고쳐야 됩니다. 소스에 아래 코드를 추가하세요: -
    Teacher.prototype.constructor = Teacher;
    -
  6. -
  7. 저장하고 다시 브라우저에서 불러오면 의도한대로 Teacher.prototype.constructorTeacher()를 반환합니다. 게다가 Person()도 상속받았죠!
  8. -
- -

Teacher()에 새 greeting() 함수 부여하기

- -

Teacher()에 새로운 greeting() 함수를 정의하여 코드를 완성합시다.

- -

가장 간단한 방법은 Teacher()의 프로토타입에 정의합니다. — 아래 코드를 추가하세요:

- -
Teacher.prototype.greeting = function() {
-  var prefix;
-
-  if (this.gender === 'male' || this.gender === 'Male' || this.gender === 'm' || this.gender === 'M') {
-    prefix = 'Mr.';
-  } else if (this.gender === 'female' || this.gender === 'Female' || this.gender === 'f' || this.gender === 'F') {
-    prefix = 'Mrs.';
-  } else {
-    prefix = 'Mx.';
-  }
-
-  alert('Hello. My name is ' + prefix + ' ' + this.name.last + ', and I teach ' + this.subject + '.');
-};
- -

조건문을 이용해서 성별에 따라 적절한 호칭이 붙은 교사의 인삿말을 alert 창으로 띄웁니다.

- -

예제 사용해 보기

- -

소스를 환성했으니 아래 코드를 통해 새 Teacher() 인스턴스를 생성해 봅시다(아니면 인자를 원하는 값으로 변경하시거나요):

- -
var teacher1 = new Teacher('Dave', 'Griffiths', 31, 'male', ['football', 'cookery'], 'mathematics');
- -

저장한 코드를 다시 불러와서 아래처럼 teacher1의 속성과 메소드를 확인해 봅시다:

- -
teacher1.name.first;
-teacher1.interests[0];
-teacher1.bio();
-teacher1.subject;
-teacher1.greeting();
-teacher1.farewell();
- -

아주 잘 실행될 겁니다. 1, 2, 3, 6 줄은 Person() 생성자(클래스)에서 상속 받은 멤버에 접근합니다. 4번째 줄은 Teacher() 생성자(클래스)만 가지고 있는 멤버에 접근합니다. 5번째 줄은 Person()에서 상속 받은 멤버도 있지만 Teacher()가 이미 자신만의 새 메소드를 정의했으므로 Teacher()의 메소드에 접근합니다.

- -
-

Note: 코드가 잘 동작하지 않으면 완성된 버전을 확인해 보세요. (실행 페이지도 보시구요).

-
- -

이 테크닉이 Javascript에서 상속 받는 클래스를 만드는 유일한 방법은 아니지만 잘 동작하며 상속을 구현하는 방법을 잘 설명하고 있습니다.

- -

조금 더 명확한 방식으로 Javascript에서 상속을 구현하는 새 {{glossary("ECMAScript")}} 기능도 관심 가질만한 주제입니다(Classes 참조). 아직까지 많은 브라우저에서 지원하지 못하고 있기 때문에 여기서 다를 주제는 아닙니다. 여러 문서에서 제시한 코드들은 IE9보다 더 오래된 구형 브라우저에서도 사용 가능하며 더 이전 버전을 지원하기 위한 방법들도 있습니다. 

- -

JavaScript 라이브러리를 쓰면 간단합니다 — 상속 기능을 사용하기 위한 보편적인 방법이죠. 예를들어 CoffeeScriptclassextends등의 기능을 제공합니다.

- -

더 연습하기

- -

OOP theory section, 에서는 개념적으로 Person을 상속받고 Teacher보다 덜 공손한 greeting() 메소드를 재정의한 Student 클래스를 정의했었습니다. 해당 절에서 Student의 인삿말이 어땠는지 확인해 보시고 Person()을 상속받는 Student() 생성자를 구현해 보세요. greeting() 함수도 재정의 해 보시구요.

- -
-

Note: 코드가 잘 동작하지 않으면 완성된 버전 을 확인해 보세요.(실행 페이지도 보시구요).

-
- -

객체 멤버 요약

- -

요약하면, 상속에 있어 고려해야 할 세 가지 유형의 속성/메소드가 있습니다:

- -
    -
  1. 생성자 함수 내에서 인스턴스에 정의하는 유형. 직접 작성한 코드에서는 생성자 함수 내에 this.x = x 구문과 유사하게 정의되어 있으므로 발견하기 쉽습니다. 브라우저 내장 코드에서는 객체 인스턴스(보통 new 키워드를 통해 생성, ex) var myInstance = new myConstructor())에서만 접근할 수 있는 멤버입니다.
  2. -
  3. 생성자에 직접 정의하는 유형, 생성자에서만 사용 가능합니다. 브라우저 내장 객체에서 흔히 사용하는 방식인데, 인스턴스가 아니라 생성자 함수에서 바로 호출되는 유형입니다. Object.key() 같은 함수들이죠.
  4. -
  5. 인스턴스와 자식 클래스에 상속하기 위해 생성자의 프로토타입에 정의하는 유형. 생성자의 프로토타이비 속성에 정의되는 모든 멤버를 의미합니다. ex) myConstructor.prototype.x().
  6. -
- -

뭐가 뭔지 헷갈려도 걱정하지 마세요 — 배우는 중이니 차츰 익숙해질겁니다.

- -

ECMAScript 2015 클래스

- -

ECMAScript 2015에서는 C++나 Java와 유사한 클래스 문법을 공개하여 클래스를 조금 더 쉽고 명확하게 재활용 할 수 있게 되었습니다. 이 절에서는 프로토타입 상속으로 작성한 Person과 Teacher 예제를 클래스 문법으로 변경하고 어떻게 동작하는지 설명하겠습니다.

- -
-

Note: 대부분의 최신 브라우저에서 새로운 클래스 작성 방식을 지원합니다만 일부 구형 브라우저(Internet Explorer가 대표적)에서는 동작하지 않으므로 하위호환성을 위해 프로토타입 상속을 배워둘 필요가 있습니다.

-
- -

Class-스타일로 재작성한 Person 예제를 보시죠:

- -
class Person {
-  constructor(first, last, age, gender, interests) {
-    this.name = {
-      first,
-      last
-    };
-    this.age = age;
-    this.gender = gender;
-    this.interests = interests;
-  }
-
-  greeting() {
-    console.log(`Hi! I'm ${this.name.first}`);
-  };
-
-  farewell() {
-    console.log(`${this.name.first} has left the building. Bye for now!`);
-  };
-}
- -

class 구문은 새로운 클래스를 작성함을 의미합니다. Class 블록 내에서 모든 기능을 정의할 수 있습니다.

- - - - - -

이제 위에서 했듯이 new 연산자로 객체 인스턴스를 생성할 수 있습니다:

- -
let han = new Person('Han', 'Solo', 25, 'male', ['Smuggling']);
-han.greeting();
-// Hi! I'm Han
-
-let leia = new Person('Leia', 'Organa', 19, 'female' ['Government']);
-leia.farewell();
-// Leia has left the building. Bye for now
- -
-

Note: 코드를 까보면 class 부분은 프로토타입 상속으로 변환이 됩니다. — 문법 설탕(syntactic sugar)의 일종인거죠. 하지만 읽기 쉽다는데 대부분 동의하실 겁니다.

-
- -

class 문법으로 상속

- -

위에서 사람을 나타내는 클래스를 만들었습니다. Person 클래스는 일반적인 사람이 가질 만한 특성들을 나열하고 있죠; 이 절에서는 Person을 class 문법으로 상속받아 Teacher 클래스를 만들 예정입니다. 이 작업을 하위 클래스 생성이라 부릅니다.

- -

하위 클래스를 만드려면 Javascript에서 extends 키워드를 통해 상속 받을 클래스를 명시합니다.

- -
class Teacher extends Person {
-  constructor(first, last, age, gender, interests, subject, grade) {
-    this.name = {
-      first,
-      last
-    };
-
-  this.age = age;
-  this.gender = gender;
-  this.interests = interests;
-  // subject and grade are specific to Teacher
-  this.subject = subject;
-  this.grade = grade;
-  }
-}
- -

constructor()에서 첫번쨰로 super() 연산자를 정의하면 코드를 조금 더 읽기 쉬워집니다. 이는 상위 클래스의 생성자를 호출하며 super()의 매개변수를 통해 상위 클래스의 멤버를 상속받을 수 있는 코드입니다.

- -
class Teacher extends Person {
-  constructor(first, last, age, gender, interests, subject, grade) {
-    super(first, last, age, gender, interests);
-
-    // subject and grade are specific to Teacher
-    this.subject = subject;
-    this.grade = grade;
-  }
-}
- -

Teacher의 인스턴스를 생성하면 의도한대로 이제 TeacherPerson 양 쪽의 메소드와 속성을 사용할 수 있습니다.

- -
let snape = new Teacher('Severus', 'Snape', 58, 'male', ['Potions'], 'Dark arts', 5);
-snape.greeting(); // Hi! I'm Severus.
-snape.farewell(); // Severus has left the building. Bye for now.
-snape.age // 58
-snape.subject; // Dark arts
- -

Person을 수정하지 않고 Teacher를 생성한 것처럼 또 다른 하위클래스도 생성할 수 있습니다.

- -
-

Note: GitHub에서 es2015-class-inheritance.html 예제를 참조하세요(실행 페이지).

-
- -

Getters와 Setters

- -

생성한 클래스 인스턴스의 속성 값을 변경하거나 최종 값을 예측할 수 없는 경우가 있을 겁니다. Teacher 예제를 보면 인스턴스를 생성하기 전에는 어떤 과목을 가르칠지 아직 모릅니다. 학기 도중에 가르치는 과목이 변경될 수도 있구요.

- -

이런 상황에 getter/setter가 필요합니다.

- -

Teacher 클래스에 getter/setter를 추가해 봅시다. 마지막에 작성했던 예제를 그대로 사용해보죠.

- -

Getter와 setter는 쌍으로 동작합니다. Getter가 현재 값을 반환한다면 그에 대응하는 setter는 해당하는 값을 변경합니다.

- -

수정된 Teacher 클래스는 아래와 같습니다:

- -
class Teacher extends Person {
-  constructor(first, last, age, gender, interests, subject, grade) {
-    super(first, last, age, gender, interests);
-    // subject and grade are specific to Teacher
-    this._subject = subject;
-    this.grade = grade;
-  }
-
-  get subject() {
-    return this._subject;
-  }
-
-  set subject(newSubject) {
-    this._subject = newSubject;
-  }
-}
- -

위 클래스를 보시면 subject 속성에 대해 getter와 setter가 생겼습니다. 멤버 변수에는 _를 붙여 getter/setter와 구분을 하였습니다. 이렇게 하지 않으면 get/set을 호출할때마다 에러가 발생합니다:

- - - -

두 기능이 실제로 어떻게 작동하는지 아래를 참조하세요:

- -
// Check the default value
-console.log(snape._subject) // Returns "Dark arts"
-
-// Change the value
-snape._subject="Balloon animals" // Sets subject to "Balloon animals"
-
-// Check it again and see if it matches the new value
-console.log(snape._subject) // Returns "Balloon animals"
- -
-

Note: GitHub에서 es2015-getters-setters.html 예제를 참조하세요(실행 페이지).

-
- -

JavaScript에서 언제 상속을 사용해야 할까?

- -

이 마지막 문서를 읽고 나면 "뭐가 이리 어렵냐"고 생각하실지도 모르겠습니다. 어렵긴 합니다 프로토타입과 상속은 Javascript에서 가장 난해한 부분이거든요. 하지만 이 부분은 Javascript가 강력하고 유연한 언어로써 작용할 수 있는 원동력이기에 충분한 시간을 들여 배울 가치가 있습니다.

- -

어찌보면 여러분은 항상 상속하고 있었습니다. Web API나 브라우저 내장 객체인 string, array 등의 메소드/속성을 사용하면서 암묵적으로 상속을 사용하고 있었던거죠.

- -

처음 시작하거나 작은 프로젝트에서 직접 상속을 구현하는 코드를 작성하는 경우는 그리 많지 않습니다. 필요하지도 않는데 상속을 위한 코드를 구현하는 건 시간 낭비에 불과하죠. 하지만 코드량이 많아질수록 상속이 필요한 경우가 생깁니다. 동일한 기능을 가진 클래스가 많아졌음을 발견했다면 기능들을 한데 묶어 공유할 수 있도록 일반 객체를 만들고 특이 객체들에게 상속하는 방식이 훨씬 편하고 유용하다는 점을 알 수 있습니다.

- -
-

Note: Javascript에서는 프로토타입을 통해 상속이 구현되어 있어 이 방식을 흔히 위임이라고 표현합니다. 특이 객체들이 일반 객체에게 일부 기능의 실행을 위임하는 것이죠.

-
- -

상속을 구현할때 상속 레벨을 너무 깊게 하지 말고, 메소드와 속성들이 정확히 어디에 구현되어 있는지 항상 인지해야 합니다. 브라우저 내장 객체의 prototype 역시 일시적으로 수정이 가능하지만 정말로 필요한 경우를 제외하고는 건드리지 말아야 합니다. 너무 깊은 상속은 디버그 할 때 끝없는 혼돈과 고통만을 줄 겁니다.

- -

궁극적으로 객체는 함수나 반복문과 같이 고유한 역할과 장점을 지닌 채 코드를 재사용하는 또 다른 방법입니다. 서로 연관된 변수와 함수들을 하나로 묶어 다룰 필요가 있을때 객체가 좋은 아이디어입니다. 한 곳에서 다른 곳으로 데이터 집합을 전달할 때에도 객체가 유용합니다. 두가지 모두 생성자나 상속 없이도 가능한 일입니다. 딱 하나의 인스턴스만 필요할 경우 객체를 선언하지 않고 객체 리터럴만으로도 충분합니다. 당연히 상속은 필요없구요.

- -

요약

- -

이 글에서는 여러분들이 반드시 알아야 할 OOJS 이론과 문법의 나머지 부분에 대해 다루고 있습니다. 이 시점에서 여러분은 javascript 객체와 OOP 기초, 프로토타입과 프로토타입 상속, 클래스(생성자)를 만들고 인스턴스를 생성하며 기능을 추가하고, 다른 클래스를 상속 받아 하위 클래스를 만드는 방법을 배웠습니다.

- -

다음 글에서는 Javascript 객체로 데이터를 교환하는 방식인 Javascript Object Notation(JSON)에 대해 알아봅시다.

- -

See also

- - - -

{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}

- - - -

In this module

- - diff --git a/files/ko/learn/javascript/objects/object-oriented_js/index.html b/files/ko/learn/javascript/objects/object-oriented_js/index.html deleted file mode 100644 index df1bf59c17..0000000000 --- a/files/ko/learn/javascript/objects/object-oriented_js/index.html +++ /dev/null @@ -1,287 +0,0 @@ ---- -title: Object-oriented JavaScript for beginners -slug: Learn/JavaScript/Objects/Object-oriented_JS -tags: - - Article - - Beginner - - CodingScripting - - JavaScript - - Learn - - 'l10n:priority' -translation_of: Learn/JavaScript/Objects/Object-oriented_JS ---- -
{{LearnSidebar}}
- -
{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}}
- -

자, 이제 기초 단계를 벗어나서,객체지향 JavaScript (OOJS) 을 보도록 하죠 — 이 문서에서 객체지향 (OOP) 이론에 대한 기초를 훑어본 후, 자바스크립트가 생성자와 함수를 통해 객체 클래스 개념을 따라했는지, 그리고 어떻게 객체를 만드는지 알아볼겁니다.

- - - - - - - - - - - - -
선수조건:컴퓨터 기본지식, HTML과 CSS에 대한 기본적인 이해,자바스크립트에 어느 정도 익숙할 것 (see First steps and Building blocks).  OOJS 기초 지식 (see Introduction to objects).
학습목표:객체지향에 대한 기본 지식을 습득 하고, 객체 지향이 자바스크립트에 어떻게 적용되었는지 ( "모든 것은 객체다") 와 어떻게 생성자와 객체 인스턴스를 만드는지에 대해 이해한다.
- -

객체지향 프로그래밍 — 기초

- -

객체지향 프로그래밍(OOP)의 개요를 설명하는 것으로 시작하겠습니다. 지금 단계에서 OOP의 모든 것을 설명면 너무 복잡해서 혼란만을 가중시킬 것이기 때문에 최대한 간단히 설명하겠습니다. OOP의 기본 컨셉은 프로그램 내에서 표현하고자 하는 실 세계(real world)의 일들을 객체를 사용해서 모델링 하고, 객체를 사용하지 않으면 불가능 혹은 무지 어려웠을 일들을 쉽게 처리하는 방법을 제공한다는 것입니다.

- -

객체는 당신이 모델링하고자 하고자 하는 일이나 기능 혹은 필요한 행동들을 표현하는 프로그램 코드와 그와 연관된 데이터로 구성됩니다. 객체는 데이터(그리고, 함수 역시)를 감싸서 ,(공식적인 표현으로는 encapsulate) 객체 패키지(해당 객체를 참조하기 위한 이름. namespace 라고도 불리죠)안에 보관합니다. 이는 계층 구조를 만드는데 용이하고 사용하기에도 쉽게 하기 위해서죠; 또한, 객체는 네트워크를 통해 쉽게 전송될 수 있도록 데이터를 저장하는 용도로도 많이 사용됩니다.

- -

객체 템플릿 정의

- -

자, 학교의 선생님과 학생들의 정보를 보여주는 간단한 프로그램이 있다고 칩시다. 여기서는 OOP의 일반적인 개념만을 살펴볼 뿐이지, 특정 언어에 국한된 내용을 이야기하지는 않을겁니다.

- -

시작해보자면, first objects article 에서 배웠던 Person 객체로 돌아가봅시다. 거기서 "사람"에 대한 기초적인 데이터와 기능을 정의했었죠. "사람"을 구별할 수 있는 특징은 많습니다 (그들의 주소, 키,신발사이즈, DNA 프로필, 여권번호, 중요한 개인적 자실 등 ...) ,하지만 이 예제에서는 오직 이름, 나이, 성별 그리고 취미만을 다룰겁니다. 여기에 더불어 이 데이터를 기반으로 각 개인에 대한 간단한 소개말과 인사말을 표시할 수 있도록 할 겁니다 . 이런 과정을 추상화 — 프로그래머의 의도에 맞추어 가장 중요한 것들만을 뽑아서 복잡한 것들을  보다 단순한 모델로 변환하는 작업 - 라고 합니다.

- -

실제 객체 생성

- -

객체 인스턴스는 클래스를 통해서 만들 수 있습니다.— 객체는 클래스에 정의된 데이터와 함수를 갖습니다. Person클래스를 통해서, 실제 '사람' 객체를 생성할 수 있습니다.:

- -

- -

클래스로부터 객체의 인스턴스가 생성될 때는 클래스의 생성자 함수 가 호출됩니다.클래스에서 객체 인스턴스가 생성되는 일련의 과정을 인스턴스화(instantiation)라고 합니다 — 객체의 인스턴스는 클래스를 통해 만들어집니다.

- -

특별한 클래스

- -

자, 이번에는 일반적인 사람이 아니라 — 일반적인 사람보다 세분화된 선생님과 학생들이 필요합니다.  OOP 에서는,특정 클래스를 기반으로 새로운 클래스를 만들 수 있습니다 — child 클래스 는 부모 클래스 상속 받아서 만들어집니다. child 클래스는 상속을 통해 부모 클래스에 정의된 데이터와 함수를 고스란히 사용할 수 있습니다. 클래스마다 기능이 달라지는 부분이 있다면, 직접 해당 클래스에 원하는 기능을 정의할 수 있습니다.

- -

- -

이것은 매우 유용합니다. 이름,성별,나이 등과 같이 선생님과 학생이 공유하는 많은 공통적인 특징들을 한번만 정의해도 되기 때문이죠. 또한 서로 다른 클래스에 같은 기능을 따로 정의할 수도 있습니다. 정의된 각각의 기능은 서로 다른 namespace에 존재하기 때문입니다. 예를 들어, 학생의 인사는 "안녕, 난 [이름]이야." 와 같은 형식이 될 것입니다. (ex) 안녕, 난 샘이야.) 반면 선생님은 "안녕하세요, 제 이름은 [성] [이름]이고 [과목명]을 담당하고 있습니다." 와 같이 좀 더 격식있는 형식을 사용할 것입니다. (ex) 안녕하세요, 제 이름은 데이브 그리피스이고 화학을 담당하고 있습니다.)

- -
-

노트: 혹시 궁금해 하실까봐 말씀드리면, 여러 객체 타입에 같은 기능을 정의할 수 있는 능력을 멋진 용어로 "다형성(polymorphism)" 이라고 합니다.

-
- -

이제 자식 클래스들로부터 객체 인스턴스를 만들 수 있습니다. 예를 들면 :

- -

- -

다음 부분에선, 어떻게 객체지향 프로그래밍 이론이 자바스크립트에 실제로 적용될 수 있는지 살펴보겠습니다.

- -

생성자와 객체 인스턴스

- -

자바스크립트는 객체와 그 기능을 정의하기 위해 생성자 함수라고 불리는 특별한 함수를 사용합니다. 이는 보통 우리가 얼마나 많은 객체들을 생성해야 할지 모르기 때문에 유용합니다. 생성자는 효율적으로 필요한 만큼 객체를 생성하고, 데이터와 함수들을 설정하는 방법을 제공합니다.

- -

생성자로부터 새로운 객체 인스턴스가 생성되면, 객체의 핵심 기능 (프로토타입에 의해 정의됩니다. Object prototypes 글에서 자세히 다룰 것입니다.)이 프로토타입 체인에 의해 연결됩니다.

- -

자바스크립트에서 생성자를 이용해 클래스를 만들고, 클래스에서 객체 인스턴스를 만드는 방법을 알아봅시다. 가장 먼저, 첫 객체 글에서 보았던 oojs.html 파일을 로컬에 새로 복사하십시오.

- -

간단한 예제

- -
    -
  1. 어떻게 일반적인 함수를 이용해 한 사람을 정의할 수 있는지부터 보겠습니다. 이 함수를 script 태그 안에 추가하세요: - -
    function createNewPerson(name) {
    -  var obj = {};
    -  obj.name = name;
    -  obj.greeting = function() {
    -    alert('Hi! I\'m ' + this.name + '.');
    -  };
    -  return obj;
    -}
    -
  2. -
  3. 이제 이 함수를 호출하여 새로운 사람을 만들 수 있습니다. 브라우저의 자바스크립트 콘솔을 열어 다음 코드를 입력해보세요: -
    var salva = createNewPerson('Salva');
    -salva.name;
    -salva.greeting();
    - 이것은 잘 작동하지만, 썩 깔끔하진 않습니다. 객체를 만들기를 원하는데, 왜 굳이 빈 객체를 만들고 내용을 채워 리턴해야 할까요? 다행스럽게도 자바스크립트는 생성자 함수의 형태로 간단한 단축 명령을 제공합니다. 하나 만들어 보도록 하죠!
  4. -
  5. 이전의 createNewPerson 함수를 다음의 코드로 교체하세요: -
    function Person(name) {
    -  this.name = name;
    -  this.greeting = function() {
    -    alert('Hi! I\'m ' + this.name + '.');
    -  };
    -}
    -
  6. -
- -

생성자 함수는 클래스의 자바스크립트 버전입니다. 이 함수가 함수가 가질 것 같은 모든 특징을 가지고 있지만, 아무것도 리턴하지 않고 객체를 만들지도 않는다는 것을 깨달으셨나요? 생성자 함수는 단순히 프로퍼티와 메소드를 정의합니다. 또 이를 정의할 때 this 라는 키워드가 사용되고 있는 것을 보실 수 있습니다. 이것은 객체 인스턴스가 생성될 때마다, 객체의 name 프로퍼티가 생성자 함수 호출에서 전달된 name 값과 같아질 것이라고 말하고 있습니다. 그리고 greeting() 메소드 역시 생성자에서 전달된 name 값을 사용할 것입니다.

- -
-

노트: 관습적으로, 생성자 함수명은 대문자로 시작하게 합니다. 이 규칙은 생성자 함수가 코드 안에서 잘 구별되도록 해줍니다.

-
- -

그래서 어떻게 생성자 함수를 호출하여 객체들을 만들까요?

- -
    -
  1. 이전 코드 아래에 다음 코드들을 추가하세요: -
    var person1 = new Person('Bob');
    -var person2 = new Person('Sarah');
    -
  2. -
  3. -

    코드를 저장하고 브라우저를 새로고침합니다. 자바스크립트 콘솔에 다음 코드를 입력해보세요:

    -
  4. -
  5. -
    person1.name
    -person1.greeting()
    -person2.name
    -person2.greeting()
    -
  6. -
- -

멋지군요! 이제 두 객체가 페이지에 생성된 것이 보입니다. 각각은 서로 다른 namespace에 저장되어있습니다. 객체의 프로퍼티와 메소드들을 사용하려면, person1 또는 person2로부터 호출하여야 합니다. 두 객체의 기능은 따로 패키징되어 서로 충돌하지 않을 것입니다. 그리고 두 Person 객체는 각각 고유의 name 프로퍼티와 greeting() 메소드를 사용할 수 있습니다. 이 둘이 생성될 때 부여받은 자신의 name 값을 사용한다는 것에 주목하십시오. 이것이 this를 사용하는 매우 중요한 이유 중 하나입니다. 객체들은 다른 값이 아니라, 그들이 가진 고유의 값을 사용합니다.

- -

생성자 호출을 다시 봅시다:

- -
var person1 = new Person('Bob');
-var person2 = new Person('Sarah');
- -

각각의 경우, new 키워드가 브라우저에게 우리가 새로운 객체 인스턴스를 만들고 싶어한다는 것을 알려줍니다. 괄호로 감싸진 매개변수들과 함께 생성자 이름을 호출하고, 결과는 변수에 담겨집니다. 일반적인 함수가 호출되는 방식과 매우 유사하죠. 각각의 인스턴스는 다음 정의에 따라 생성됩니다.

- -
function Person(name) {
-  this.name = name;
-  this.greeting = function() {
-    alert('Hi! I\'m ' + this.name + '.');
-  };
-}
- -

새 객체가 생성된 이후, person1person2 변수는 다음 객체들을 가지게 됩니다.

- -
{
-  name: 'Bob',
-  greeting: function() {
-    alert('Hi! I\'m ' + this.name + '.');
-  }
-}
-
-{
-  name: 'Sarah',
-  greeting: function() {
-    alert('Hi! I\'m ' + this.name + '.');
-  }
-}
- -

우리가 생성자 함수를 호출할 때마다 매번 greeting() 함수를 다시 정의하는 것이 보입니다. 최선의 방법은 아니죠. 이를 피하기 위해, 우리는 prototype에 함수를 정의합니다. 이를 차후에 다시 살펴보겠습니다.

- -

생성자 완성시키기

- -

위에서 살펴본 예제는 시작에 불과합니다. 최종적인 Person() 생성자를 만들어봅시다.

- -
    -
  1. 여태 작성한 코드를 지우고 아래의 생성자로 대체하세요. 원리는 이전의 예제와 똑같으며, 약간 더 복잡할 뿐입니다: -
    function Person(first, last, age, gender, interests) {
    -  this.name = {
    -    'first': first,
    -    'last' : last
    -  };
    -  this.age = age;
    -  this.gender = gender;
    -  this.interests = interests;
    -  this.bio = function() {
    -    alert(this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
    -  };
    -  this.greeting = function() {
    -    alert('Hi! I\'m ' + this.name.first + '.');
    -  };
    -}
    -
  2. -
  3. 이제 생성자로 객체 인스턴스를 만들기 위해, 아래에 이 코드를 추가하세요: -
    var person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);
    -
  4. -
- -

이제 이전에 해보았듯이, 브라우저의 자바스크립트 콘솔에서 프로퍼티와 메소드를 사용할 수 있습니다:

- -
person1['age']
-person1.interests[1]
-person1.bio()
-// etc.
- -
-

노트: 만약 실행에 문제가 생긴다면, 저희가 준비한 코드와 비교해보세요. oojs-class-finished.html (또한 실제로 실행되는 모습을 보세요).

-
- -

추가 예제

- -

이를 시작하기 위해서, 몇 개의 객체를 더 생성하는 코드를 추가해보세요. 그리고 생성된 객체 인스턴스의 멤버들을 사용하거나 바꿔보세요.

- -

더 나아가, 우리의 bio() 메소드엔 몇 가지 문제점이 있습니다. 먼저 결과가 항상 대명사 "He"를 포함한다는 점입니다. 생성된 사람이 여성이거나 다른 성별 분류를 가질지라도 말이죠. 그리고 interests 배열에 몇 개가 포함되어 있더라도 bio는 2개의 취미만을 출력합니다. 클래스 정의 (생성자)에서 이를 해결할 방법이 있을까요? 자유롭게 생성자를 수정해보세요. (약간의 조건문과 반복문이 필요할지도 모르겠습니다). 어떻게 성별에 따라, 혹은 취미의 개수에 따라 문장이 다르게 구성되어야할지 생각해보세요 .

- -
-

노트: 하다가 막힌다면, 저희가 제공하는 GitHub 저장소의 모법 답안 (그리고 실행 버전)을 참고하세요. 하지만 일단 직접 해보시죠!

-
- -

객체 인스턴스를 생성하는 다른 방법들

- -

여태까지 객체 인스턴스를 만드는 두 가지 방법을 살펴보았습니다. 객체 리터럴을 선언하는 방법과, 생성자 함수를 사용하는 방법(위를 보세요)이죠.

- -

이것들은 잘 동작하지만, 다른 방법들도 있습니다. 웹에서 정보를 찾다가 마주칠 경우를 대비해 익숙해져보는 것도 좋을 것 같습니다.

- -

Object() 생성자

- -

첫번째로, 새 객체를 만들기 위해 Object() 생성자를 사용할 수 있습니다. 네, 최초의 object 역시 생성자를 가지고 있습니다. 빈 객체를 생성하는 함수이죠.

- -
    -
  1. 브라우저의 자바스크립트 콘솔에 아래 코드를 입력해보세요: -
    var person1 = new Object();
    -
  2. -
  3. 이는 빈 객체를 person1 변수에 담습니다. 이제 이 객체에 점 표기법이나 괄호 표기법을 이용해 프로퍼티와 메소드들을 추가할 수 있습니다. 이 예제 코드를 콘솔 창에 입력해보세요. -
    person1.name = 'Chris';
    -person1['age'] = 38;
    -person1.greeting = function() {
    -  alert('Hi! I\'m ' + this.name + '.');
    -};
    -
  4. -
  5. 사전에 프로퍼티와 메소드를 정의하기 위해, Object() 생성자의 파라미터로 객체 리터럴을 전달할 수도 있습니다. 이 예제 코드를 콘솔 창에 입력해보세요. -
    var person1 = new Object({
    -  name: 'Chris',
    -  age: 38,
    -  greeting: function() {
    -    alert('Hi! I\'m ' + this.name + '.');
    -  }
    -});
    -
  6. -
- -

create() 함수 사용

- -

생성자는 여러분의 코드에 규칙을 부여해줍니다. 일단 생성자를 만들어두면, 이를 이용해 원하는대로 인스턴스를 생성할 수 있고, 이 인스턴스가 어디서 유래했는지 명백합니다.

- -

하지만 몇몇 사람들은 객체 인스턴스들을 생성할 때 먼저 생성자를 만들기를 원하지 않습니다. 특히 그들이 적은 수의 객체만을 생성할 때 말이죠. 자바스크립트는 create()라는 내장함수를 가지고 있어 이를 가능하게 해줍니다. 이를 이용하면, 이미 존재하는 객체를 이용해 새로운 객체를 만들 수 있습니다.

- -
    -
  1. 이전 섹션에서 완료한 예제를 브라우저에서 열어, 아래 코드를 콘솔창에 입력해보세요. -
    var person2 = Object.create(person1);
    -
  2. -
  3. 이제 이 코드를 입력해보세요. -
    person2.name
    -person2.greeting()
    -
  4. -
- -

person2person1을 기반으로 만들어졌습니다. 새 객체는 원 객체와 같은 프로퍼티와 메소드들을 가집니다. 

- -

create() 함수의 한 가지 단점은 익스플로러 8에서는 지원하지 않는다는 점입니다. 따라서 오래된 브라우저들까지 지원하고 싶다면 생성자를 사용하는 것이 효과적입니다.

- -

다음에 create() 함수의 효과에 대해 더 살펴보겠습니다.

- -

요약

- -

이 글은 객체지향 이론을 요약하여 설명해줍니다. 모든 부분을 다루지는 않지만, 지금 어떤 것들을 다루고 있는지에 대한 아이디어 정도는 얻을 수 있습니다. 게다가 객체 인스턴스를 생성하는 여러가지 방법에 대해서도 알아보기 시작했습니다.

- -

다음 글에서는 자바스크립트 객체 프로토타입에 대해 탐험해보겠습니다.

- -

{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}}

- -

In this module

- - - -

 

-- cgit v1.2.3-54-g00ecf