💡 Q1. Class는 대체로 추상화를 위해 사용됩니다. ES5 자바스크립트에서 Class는 어떻게 동작할까요?
프로토타입 기반(prototype-base) 객체지향 프로그래밍(OOP)
- JS는 명령형(imperative), 함수형(functional), 프로토타입 기반(prototype-based) 객체지향 언어다.
- 보통 사람들이 객체지향 프로그래밍(**OOP)**라고 하는 것은, 사실상, JAVA/C++과 같은 클래스 기반 객체지향 프로그래밍을 말한다.
- JavaScript에서는 클래스 기반이 아닌, 프로토타입 기반의 객체지향 프로그래밍이 가능하다.
- JS에서 Class 문법은 ES6에서 등장하였고, 사실상 JAVA/C++과 같이 Class 기반 객체지향 프로그래밍에 익숙한 사람들을 위해 만들어진 Syntatic Sugar이다.
- JS에서 Class는 사실 함수이고, 위에서 말한 prototype패턴을 기반으로 한다.
- JS에서 모든 객체는 prototype이라는 빌트인 객체를 갖는다.
- prototype은 생성자 함수의 메서드를 정의하는 별도의 객체이며, prototype도 자체 prototype 빌트인 객체를 가지고 있어서 prototype chain을 만들 수 있다. 체인은 null 값을 가진 prototype에 도달하면 끝난다.

Class 문법 사용하지 않고 class 구현하는 법
- 생성자 function + new 연산자 조합을 이용해 객체를 생성할 수 있다.
- 생성자 함수는 클래스이자 생성자의 역할을 한다.
- prototype을 사용하지 않았을 때, 객체 인스턴스의 문제점 : 모든 인스턴스가 동일한 메소드를 ownProperty로 소유함 → 메모리 낭비 → 이를 해결하기 위해 prototype 활용한다.
// 생성자 함수(Constructor)로 + new 연산자로 객체 생성 function Person(name) { // 프로퍼티 this.name = name; // 메소드 this.setName = function (name) { this.name = name; }; // 메소드 this.getName = function () { return this.name; }; } const me = new Person("Choi") const you = new Person("Kim") console.log(me, Object.getPrototypeOf(me)) // Person { name: 'Choi',setName: [Function (anonymous)], getName: [Function (anonymous)]} {} console.log(you, Object.getPrototypeOf(you)) // Person { name: 'Kim', setName: [Function (anonymous)], getName: [Function (anonymous)]} {} // 메소드를 Person 생성자 함수의 prototype에 추가 function Person(name) { // 프로퍼티 this.name = name; } function setName(name) { this.name = name } function getName(name) { return this.name; } Person.prototype.setName = setName Person.prototype.getName = getName const me = new Person("Choi") const you = new Person("Kim") console.log(me, Object.getPrototypeOf(me)) // Person { name: 'Choi' } { setName: [Function: setName], getName: [Function: getName] } console.log(you, Object.getPrototypeOf(you)) // Person { name: 'Kim' } { setName: [Function: setName], getName: [Function: getName] }
- 생성자 함수는 클래스이자 생성자의 역할을 한다.
Prototype에 속성 추가하기
- 다른 객체를 바탕으로 만들어진 객체는 원본 객체의 속성을 prototype으로 갖는다.
- 위에서 보았 듯, 함수와 new 생성자를 함께 사용하게 되면, 해당 속성이 새롭게 만들어진 객체의 prototype으로 설정된다. (관례적으로 __proto__라는 이름의 속성으로 저장)
- __proto__는 Object.prototype의 액세서리 속성으로, getter와 setter 함수를 대신할 수 있다. 원래 ECMAScript에 언어 스펙에 포함되지 않았지만, 브라우저단에서 동작하도록 구현했다. 하지만 __proto__의 사용은 권장되지 않고, 이제는 deprecated되어 많은 최신 버전의 브라우저에서 지원하지 않는다고 한다.
- __proto__대신. Object.getPrototypeOf, Obejct.setPrototypeOf를 사용하면 된다. (tmi : Object.setPrototypeOf를 사용해서 객체의 [[prototype]]을 변경하는 것은, JS 엔진에 엄청난 부하를 건다고 한다. MDN에서는 성능이 중요하다면 이 방법 대신 원하는 prototype을 가진는 새로운 객체를 생성하고, Object.create()을 사용하는 방법을 권장한다. + Object.assign을 사용할 수도 있다.)
const obj1 = { name : "obj1", logging : function () { return console.log(`this name is ${this.name}`); } } console.log(Object.getPrototypeOf(obj1)); // [Object: null prototype] {} const obj2 = Object.create(obj1) console.log(obj2); // {} console.log(Object.getPrototypeOf(obj2)) // { name: 'obj1', logging: [Function: logging] } console.log(obj2.name); // obj1 console.log(obj2.logging()); // this name is obj1 // 생성자 함수 prototype에 추가할 함수 function hello(){ return console.log(`${this.name} : hello`); } // 객체 생성자로 사용할 함수 function Person(name) { return this.name = name; } // Person 생성자 함수의 속성, prototype이 포함 console.log(Object.getOwnPropertyNames(Person)); // [ 'length', 'name', 'arguments', 'caller', 'prototype' ] // Person 생성자 함수 prototype에 hello 함수 추가 Person.prototype.hello = hello console.log(Person.prototype.hello); // [Function: hello] // Person 함수 + new 생성자로 yena 객체 생성 // yena 객체의 prototye을 조회하면, hello 함수가 있음 const yena = new Person('yena') console.log(yena.hello()); // yena : hello console.log(yena.__proto__); // { hello: [Function: hello] } // Object.assign()을 통해 Person 함수의 prototype에 personPrototype을 추가 const personPrototype = {greet() { return console.log(`nice to meet you. I'm ${this.name}`)}} Object.assign(Person.prototype, personPrototype) console.log(Person.prototype); // { hello: [Function: hello], greet: [Function: greet] } // yena 객체는 Person 객체의 prototype을 참조하고 있으므로, // yena.prototype = personPrototype을 할당하지 않아도 greet()을 메서드로 가짐 console.log(yena.greet()); // nice to meet you. I'm yena
Object-Oriented Programming | PoiemaWeb
오늘날 많은 유명한 프로그래밍 언어(Java, C++, C#, Python, PHP, Ruby, Object-C)는 객체지향 프로그래밍을 지원한다.
poiemaweb.com
Object-oriented programming - Learn web development | MDN
This article has described the basic features of class-based object oriented programming, and briefly looked at how JavaScript constructors and prototypes compare with these concepts.
developer.mozilla.org
Object prototypes - Learn web development | MDN
This article has covered JavaScript object prototypes, including how prototype object chains allow objects to inherit features from one another, the prototype property and how it can be used to add methods to constructors, and other related topics.
developer.mozilla.org
'항해99_10기 > 105일의 TIL & WIL' 카테고리의 다른 글
| [5주차] [20221212] 3 Layered Architecture Pattern에서 테스트 코드를 위한 의존성 주입 (feat. 생성자 주입, jest.js) (0) | 2022.12.12 |
|---|---|
| [4주차 WIL] 2022.12.05 ~ 2022.12.10 회고 (0) | 2022.12.11 |
| [TIL] [5주차] [20221209] object literal에서 spread operator (1) | 2022.12.09 |
| [TIL] [4주차] [20221208] 4주차 회고 - 코드리뷰와 리팩토링 / package.json, EC2 set locale, express sanitizer (1) | 2022.12.09 |
| [4주차] [20221208] node.js의 require() 작동 방식 (0) | 2022.12.08 |