티스토리 뷰
https://www.notion.so/simsimjae/14-a118180e1c224db0ad73725f83b5bdbb
아래 글들은 검색엔진 노출을 위한 글입니다.
노션에서 확인하시면 이미지와 함께 정리된 글을 보실수 있습니다. 궁금하신점은 블로그 댓글이나 노션 코멘트를 이용해주세요(@comment)
제가 직접 만든 프로젝트입니다.
http://pickvs.com : 닥전닥후
도입부
ES6이전까지 자바스크립트에는 Class라는 키워드가 없었다. 따라서, 객체지향 디자인 패턴을 따라하기 위해서 각자 개발에서 사용하곤 했다.
하지만 ES6에 드디어 도입이 되어서 다른 언어에서 유입되는 개발자들이 좀 더 편하게 개발할 수 있게 되었다. Class라는 키워드는 어떤 추가 기능을 제공하는게 아니라 원래 있었던 객체지향의 특징들을 구현하기 위해 더짧고 깔끔한 코드를 제공한다.
클래스도 함수의 한 종류이다.
const x = function() {} // 함수 표현식 const y = class {} // 클래스도 함수이다. Object.getPrototypeOf(x) Object.getPrototypeOf(y) // 둘다, f() { [native code] } 출력 -> Function.prototype을 의미함.
- 객체가 가진 [[Prototype]]속성에 접근하기 위해 직접적으로 Object.__proto__와 같이 접근한게 아니라 getPrototypeOf 메소드를 통해서 접근했다.
- 함수호출시 new키워드를 함께 사용하면 그 함수가 생성자로 동작한다.
- class도 함수이므로 new class를 하게 되면 마찬가지로 생성자로 동작한다.
- 함수가 그냥 호출될때랑 new키워드와 함께 생성자로 호출될때 차이를 구분하기 힘드므로 관행적으로 생성자 함수는 첫글자를 대문자로 쓰는것처럼, 클래스는 항상 생성자로 사용되기 떄문에 첫글자를 대문자로 써야 한다.
메소드 정의 방식 변경
ES6 이전
function Hero(name, level) { this.name = name; this.level = level; } // Adding a method to the constructor Hero.prototype.greet = function() { return `${this.name} says hello.`; }
- 위와 같이 프로토타입에 메소드를 정의하는 방식.
- Hero 생성자 함수에 의해 생성된 모든 객체는 [[prototype]] 속성으로 생성자 함수의 프로토타입 객체에 접근할 수 있음. 그 객체에 메소드가 정의된것과 동일한 효과.
ES6 Class 키워드 도입 이후
class Hero { constructor(name, level) { this.name = name; this.level = level; } // Adding a method to the constructor greet() { return `${this.name} says hello.`; } }
-
위 두개의 코드는 같은 일을 하는 코드인데 Class를 사용한 코드가 훨씬 직관적이다.
const hero1 = new Hero('simsimjae', 1); console.log(hero1);
//Output Hero {name: "simsimjae", level: 1} proto: ▶ constructor: class Hero ▶ greet: ƒ greet()
-
Hero 클래스의 인스턴스인 hero1를 콘솔에 찍어보면 생성자 함수를 이용한 방법과 똑같은 방식으로 동작하는 것을 알 수 있다.
-
Hero라는 클래스 인스턴스는 __proto__ 속성으로 Hero함수(=class)의 프로토타입 객체를 가리키며 그 프로토타입 안에는 greet이라는 메서드가 정의되어 있다.
-
원문에서 이러한 과정들이 내부적으로 이뤄지기 때문에 클래스를 통한 객체 생성은 비 직관적이다 라고 얘기를 하고 있는데 이미 내부 과정을 이해한 뒤에는 굳이 일일이 프로토타입에 메서드를 정의하는 귀찮은 방식보다는 class키워드를 통해서 간편하고 깔끔하게 객체를 만드는게 좋은것 같다.
상속
- 영웅의 한 종류인 마법사 클래스를 정의해보자.
ES6이전 방식
function Mage(name, level, spell) { Hero.call(this, name, level); // Hero(부모 역할) 함수를 실행시키되, 그 함수 내부에서 this는 여기서의 this(Mage객체)로 하겠다. // 그리고 인자는 name과 level이다. // 부모 함수를 자식이 빌려 사용해서 자식 본인의 멤버변수를 초기화 하는 셈이다. // 부모 함수의 변수들은 부모의 생성자 함수를 통해서 초기화 한다. this.spell = spell; // 자식에서만 사용하는 변수 }
같은 일을 ES6에서는 Super키워드로 할 수 있다.
class Mage extends Hero { constructor(name, level, spell) { super(name, level); // Hero.call(this, name, level);과 같은 역할 this.spell = spell; } }
- 두 방식은 거의 90%이상이 똑같지만 약간 다른점이 있다.
- ES6이전 방식으로 상속을 구현하면 단순히 부모 역할을 하는 생성자 함수를 빌려서 자식 객체를 초기화 하는것이므로 자식 객체의 [[Prototype]]을 따라가면 자식 함수의 프로토타입 객체가 있다.(Mage.prototype)
- 하지만, ES6이후 방식인 Class키워드를 통해 상속을 하게 되면 생성된 자식 객체의 [[prototype]]링크는 실제로 부모 함수(Hero)를 가리킨다.
결론
자바스크립트에서 상속이 어떻게 동작하는지 프로토타입 기반 상속을 이해한뒤, Class키워드를 통해 쉽고 간결하고 깔끔하게 상속을 구현하도록 하자. 다른 객체지향 언어에서도 너무나도 흔하게 사용되는 키워드이기 때문에 배워두면 쓸 곳이 많다.
'Javascript' 카테고리의 다른 글
#20 순수함수와 사이드 이펙트 (0) | 2019.09.26 |
---|---|
#14-2 팩토리 패턴 vs 클래스 어떤것이 객체 생성에 더 좋은 방법일까? (0) | 2019.09.25 |
#13 자바스크립트 DOM 이해하기 (0) | 2019.09.25 |
#12 자바스크립트 비트연산 활용하기 (0) | 2019.09.25 |
#11 V8엔진이 JS를 기계코드로 바꾸는 방법 (0) | 2019.09.25 |
- Total
- Today
- Yesterday
- webpack
- props
- await
- rendering scope
- atomic design
- mobx
- es6
- useEffect
- typescript
- javascript
- state
- server side rendering
- Polyfill
- reducer
- react hooks
- react
- reflow
- return type
- promise
- Babel
- Next.js
- type alias
- useRef
- Action
- async
- storybook
- hydrate
- computed
- design system
- reactdom
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |