자바스크립트 상속에 관한 일반적인 오해들

🗓 2015-05-06

의역과 오역이 난무합니다.!!^^ 내용상 중요하지 않은 부분은 생략했습니다. 오역에 대한 제보 언제든지 환영합니다.

Common Misconceptions About Inheritance in JavaScript by Eric Elliott
자바스크립트 상속에 대한 일반적인 오해들

원문

https://medium.com/javascript-scene/common-misconceptions-about-inheritance-in-javascript-d5d9bab29b0a


"프로토타입을 이해하지 못했다면 당신은 자바스크립트를 이해하지 못하는것이다."

Q. 클래스 방식의 상속과 프로토타입의 상속은 사실상 같은 것이고, 단지 스타일적인 취향이다?

"아니다"

클래스와 프로토타입의 상속방식은 근본적으로 그리고 의미적으로 다르다 두 방식은 몇가지 뚜렷한 특징이 있다. 이 몇가지 포인트를 기억하기 바란다.

  • 클래스 상속 방식에서는 인스턴스가 클래스라는 블루프린트에서 상속받고 서브클래스와의 관계를 만든다.

다른말로 클래스를 인스턴스처럼 사용할수 없고 클래스 정의된 인스턴스 메소드를 호출 할 수 없다. 인스턴스 메소드를 실행하려면 반드시 인스턴스를 만들고 실행해야 한다.

  • 프로토타입 상속에서는 인스턴스는 다른 인스턴스를 상속 받게 된다. 위임 프로토타입(delegate prototype)을 이용하면 카일 심슨이 말한 Object Linking to Other Objects(OLOO)에 가까운데,

원형 객체를 참조하는 한개의 인스턴스를 프로토타입으로 정의한다. Concatenative 상속을 이용하면 단순히 원형 객체의 프로퍼티를 새로운 인스턴스에 복사한다.

이것들의 차이를 이해하는것은 매우 중요하다. 클래스 방식은 그 자체의 메커니즘에 의해 서브클래스를 만드는 사이드 이팩트로 클래스 계층구조가 만들어진다. 이런 계층구조는 바꾸기 힘든 코드(arthritic code)의 원인이 되고 베이스 클래스를 수정하게되면 그 사이드 이팩트로 인해 쉽게 깨진다.

프로토타입방식의 상속은 이런 계층구조를 만들 필요가 없다. 프로토타입 체인을 가능한 얕게 유지할것을 추천한다. 그러면 단일 위임 프로토타입을 만들기 위해 함께할 많은 프로토타입이 수평적으로 유지될것이다.

TL;DR:

  • 클래스는 블루프린트이다.
  • 프로토타입은 객체 인스턴스이다.

Q. 클래스는 자바스립트의 오브젝트를 만들기 위한 옳은 방향이 아니다?

"그렇다"

자바스크립트로 객체를 생성하는 방법은 여러가지가 있다. 가장 일반적인 방법은 오브젝트 리터럴을 이용하는것으로 아래와같다(ES6)

let mouse = {
  furColor: 'brown',
  legs: 4,
  tail: 'long, skinny',
  describe () {
    return `A mouse with ${this.furColor} fur,
      ${this.legs} legs, and a ${this.tail} tail.`;
  }
};

오브젝트 리터럴은 ES6보다 훨씬 오래전부터 사용되었지만 위에 나타나는 메소드 숏컷과 var대신 let의 사용한점 그리고 describe메소드 안의 템플릿 스트링은 ES5에서는 작동하지 않는다. ES5의 기능인 Object.create()을 이용해 위임 프로토타입을 연결할수 있다.

let animal = {
  animalType: 'animal',

  describe () {
    return `An ${this.animalType}, with ${this.furColor} fur,
      ${this.legs} legs, and a ${this.tail} tail.`;
  }
};

let mouse = Object.assign(Object.create(animal), {
  animalType: 'mouse',
  furColor: 'brown',
  legs: 4,
  tail: 'long, skinny'
});

animal은 위임 프로토타입이고 mouse는 인스턴스이다. mouse에 없는 프로퍼티에 접근하려 한다면 자바스크립트 런타임은 animal(프로토타입)의 프로퍼티에서 찾게 될것이다.

Object.assign()은 ES6의 새로운 기능으로 여러 라이브러리에 이미 구현해 왔던 기능인데 jQuery와 Underscore의 extend()는 들어봤을 것이다. 첫번째 인자로 타겟오브젝트넘기고 그뒤로 소스오브젝트를 컴마로 구분해서 넘기면 소스오브젝트의 Enumarable한 고유 프로퍼티들을 마지막의 객체를 우선으로 타겟오브젝트에 복사한다. 만약 소스 오브젝트중에 겹치는 프로퍼티이름이 있다면 마지막의 객체의 프로퍼티가 들어가게 된다.

Object.create()는 ES5의 기능으로 컨스트럭터와 new 키워드를 사용하지 않고 위임 프로토타입을 연결 하게 해준다

추천하지 않기때문에 이글에서는 컨스트럭터를 이용한 예제를 건너뛸것이다. 나는 그것들이 잘못 사용되는것을 많이 봐왔고 많은 부분에서 문제를 일으켰다. 많은 똑똑한 사람들이 나의 의견에 동의 하지 않는것은 중요하지 않다. 어쨌든 그들은 본인들이 원하는 것을 할것이다.

지혜로운 사람들은 더글라스 크록포드의 조언을 수용할것이다.

"만약 어떤 기능이 가끔 위험한데 조금이라도 나은 방법이 있다면 항상 나은 방법을 이용해라"


Q. 오브젝트를 정의하거나 객체 초기화를 위해 컨스트럭터가 필요하지 않나?

"아니다"

어떤 펑션도 객체를 만들거나 리턴 할수 있다. 만약 그것이 컨스터럭터 펑션이 아니라면 팩토리 펑션이라고 부른다.

The Better Option

let animal = {
  animalType: 'animal',

  describe () {
    return `An ${this.animalType} with ${this.furColor} fur,
      ${this.legs} legs, and a ${this.tail} tail.`;
  }
};

let mouseFactory = function mouseFactory () {
  return Object.assign(Object.create(animal), {
    animalType: 'mouse',
    furColor: 'brown',
    legs: 4,
    tail: 'long, skinny'
  });
};

let mickey = mouseFactory();

나는 일반적으로 팩토리에 'Factory'라는 이름을 붙이지 않지만 예시로 붙여봤다. 보통이라면 mouse()라고 이름을 지었을 것이다.


Q. 자바스크립트의 은닉화를 위해 컨스트럭처가 필요하지 않나?

"아니다"

자바스크립트는 함수를 정의한 외부영역의 변수에 언제든지 접근 가능한 함수를 만들 수 있는데 이럴때 자바스크립트 엔진은 클로저를 만든다. 클로저는 일반적으로 사용되는 자바스크립트 패턴으로 데이터의 은닉을 위해 사용된다.

컨스트럭처 펑션뿐 아니라 어떤 펑션이던 데이터의 은닉을 위해 클로저를 만들수 있다.

let animal = {
  animalType: 'animal',

  describe () {
    return `An ${this.animalType} with ${this.furColor} fur,
      ${this.legs} legs, and a ${this.tail} tail.`;
  }
};

let mouseFactory = function mouseFactory () {
  let secret = 'secret agent';

  return Object.assign(Object.create(animal), {
    animalType: 'mouse',
    furColor: 'brown',
    legs: 4,
    tail: 'long, skinny',
    profession () {
      return secret;
    }
  });
};

let james = mouseFactory();

Q. "new"는 코드가 클래스 상속을 이용한다는 뜻인가?

"대츠 노~ 노~"

'new' 키워드는 컨스트럭처를 실행하는데 사용된다. 정확히 무엇하냐면

  • 새로운 인스턴스를 생성한다.
  • 생성된 인스턴스에 this를 바인드한다.
  • 새로운 인스턴스의 위임 '[[Prototype]]'을 컨스트럭처의 prototype 프로퍼티에 의해 참조되는 객체에 연결한다.
  • 컨스트럭처의 이름을 따서 오브젝트 타입의 이름으로 정한다 이는 나중에 디버깅 콘솔에서 '[Object object]'대신에 '[Object foo]'로 보여진다.
  • instanceof로 오브젝트의 프로토타입 참조가 같은 컨스트럭터의 프로토타입 프로퍼티의 참조 객체인지 확인할 수 있게 한다.

'instanceof'의 거짓말

잠시 멈추고 'instanceof'에 대해 재고해보자. 아마 이것의 유용성에 대해 마음을 바꾸게 될것이다.

'instanceof'는 예상한대로 엄격한 타입 체크 언어와 비슷하게 타입을 체크하지 않는다. 대신에 prototype객체에 대한 동일성만 체크 한다. 이런 방식은 좀 멍청하다. 이렇게 하면 다른 실행 컨텍스트간의 타입체크에서 제대로 역할을 하지 못한다.

긍정과 부정에 대해 쉽게 잘못된 결과를 얻을수 있다. 타겟오브젝트와의 프로토타입 프로퍼티의 동일성만 체크하기때문에 아래와 같이 이상한 일이 생긴다.

function foo() {}
var bar = { a: ‘a’};
foo.prototype = bar; // Object {a: “a”}
baz = Object.create(bar); // Object {a: “a”}
baz instanceof foo // true. oops.

마지막의 결과는 자바스크립트 명세에 완벽히 부합하는 결과이다. 'instanceof'는 타입에 대한 안전을 보장하지 않는다.

게다가 자바스크립트 코드를 마치 엄격한 타입의 코드인양 행동하게해 펑션으로 하여금 재사용가능하고 유용한 제너릭으로 향하는것을 방해 한다.

'instanceof'는 당신의 코드의 재사용성을 제한하고 잠재적인 버그를 당신의 코드에 심어두게 된다.

'instanceof'는 거짓말한다. 대신에 Ducktype을 이용하자

'new' is weird

'new' 역시 리턴값에 대해 이상한 모습을 보이는 키워드이다. 만약 원시타입을 리턴하려한다면 원하는 결과를 얻지 못할 것이다. 하지만 어떤 형태로든 객체를 리턴하게되면 원하는 대로 동작은 하게 되지만 'this'에 옳바른 결과는 기대할수 없고 'this'를 참조해 사용하는 모든것들이 깨지며(call()이나 apply()같은) 생성자의 prototype에 대한 연결 역시 깨지게 된다


Q. 클래스 상속과 프로토타입 상속 간에 큰 퍼포먼스 차이가 있나?

"아니다"

히든 클래스에 대해 들어본적이 있을것이고 컨스트럭처가 'Object.create()'의 객체들의 생성을 드라마틱하게 능가할리라 생각할것이다. 이런 성능차이는 드라마틱하게 과장되어 졌다.

어플리케이션이 구동될때 적은 시간이 자바스크립트를 실행하는데 사용되고 훨씬더 적은 시간이 객체들의 프로퍼티들에 접근하는데 사용된다. 사실 요즘 생산되는 가장 느린 랩탑도 초당 수백만의 프로퍼티에 접근할수 있다.

그건 어플리케이션의 보틀넥이 아니다. 당신의 어플리케이션을 프로파일해 퍼포먼스를 저해하는 진짜 보틀넥을 발견해보자. 아마도 micro-optimization을 생각하기 전에 해결해야할 수많은 문제점들을 발견 하게될것이다.

확신 할수 없는가? micro-optimazation이 앱에 큰 영향을 주기위해서는 수만번의 작업을 반복해야 할것이고 당신은 정작 고려해야할 micro-optimization의 차이점들은 100배 이상의 차이여야 할것이다.

Rule of thumb: 우선 당신의 어플리케이션안에서 찾을수 있는 수많은 로딩, 네트워킹, 파일 I/O 그리고 렌더링 보틀넥을 해결한뒤에 그때 micro-optimiztion을 생각해도 늣지 않는다.

.0000000001초와 .000000001초의 차이점을 말할수 있는가? 나역시 못한다. 그러나 10개의 아이콘의 로딩의 차이나 웹폰트 로딩의 차이는 말할수 있을것이라 확신한다.

만약 당신의 어플리케이션을 프로파일해봤는데 객체생성이 진짜 보틀넥이라고 판단된다면 빠른 해결책은 'new'를 사용하는 방식이나 클래스방식의 상속이 아닌 객체리터럴을 이용하는 방법이 될것이다. 루프안에서 객체리터럴로 객체를 생성하고 그객체들을 오브젝트 풀에 추가해 가비지 컬렉터로 인해 지워지지 않게 한다. 만약 퍼포먼스를 위해 프로토타입 상속을 포기할수 있다면 프로토타입 체인과 상속으로 얻을것들을 계속 객체 리터럴로 정의하는것을 감수해야할 것이다.

하지만 구글에선 클래스가 빠르다고 했다.

구글은 자바스크립트 엔진을 만들고 있고 당신은 어플리케이션을 만들고 있다. 명백히 그들이 중요하게 생각하는것과 당신이 중요하게 생각하는것은 매우 다를 것이다. 구글이 micro-optimizations처리할때 당신은 당신의 어플리케이션의 진짜 보틀넥을 걱정하면 된다. 다른것에 신경쓰는것보다 훨씬 좋은 ROI가 나올거라고 장담한다.


Q. 클래스 상속과 프로토타입 상속 간에 메모리 사용량에 큰 차이가 있는가?

"아니다"

둘다 많은 인스턴스 간의 메소드 공유를 위해 위임 프로토타입이 사용되고 불필요한 클로저생성을 줄이게 된다. 사실 팩토리 펑션으로 시작한다면 오브젝트 풀을 변경하는게 훨씬 쉬워져 메모리를 관리를 꼼꼼히 할수있고 가비지 컬렉터에 의해 주기적으로 차단되는것을 막을수 있다. 이런게 왜 컨스터럭처를 이용했을시에 어려운지는 **'new' 는 코드가 클래스 상속을 이용한다는 뜻인가?**파트를 확인하기 바란다. 다시 말해 가장 유연하게 메모리관리를 하고 싶다면 컨스트럭터와 클래스 상속 대신 팩토리 펑션을 이용해라.


Q. 네이티브 API들은 컨스트럭터를 사용한다. 그게 조금 더 팩토리보다는 관용적이지 않나?

"아니다"

자바스크립트에서 팩토리는 지극히 일반적이다. 예를들면 자바스크립트 라이브러리중 제일 유명한 jQuery는 팩토리를 이용한다. 존래식은 클래스 대신 팩토리와 프로토타입 확장을 선택한것에 대한 글을 썼다. 기본적으로 그는 라이브러리 사용자가 셀렉을 할때마다 매번 'new'를 입력하는것을 원치 않았던것이다. 만약 아래와 같이 보였다면 어땠을까?

/**
  classy jQuery - an alternate reality where jQuery really sucked and never took off
  OR
  Why nobody would have liked jQuery if it had exported a class instead of a factory.
  **/

// This just looks stupid. Are we creating a new DOM element
// with id="foo"? Nope. We're selecting an existing DOM element
// with id="foo", and wrapping it in a jQuery object instance.
var $foo = new $('#foo');

// Besides, it's a lot of extra typing with literally ZERO gain.
var $bar = new $('.bar');
var $baz = new $('.baz');

// And this is just... well. I don't know what.
var $bif = new $('.foo').on('click', function () {
var $this = new $(this);
    $this.html('clicked!');
});

이밖에도..

  • React의 'React.creatClass()'는 팩토리이다.
  • Angular는 클래스와 팩토리를 같이 사용한다. 그러나 모두 DI 컨테이너 안에서 팩토리로 감싸져 있다.
  • Ember에서는 'Ember.Application.create();'라는 팩토리를 앱을 만들때 사용하고 'new'대신 'extend()'메소드를 이용해 앱을 확장한다.
  • Node의 코어서비스들은 팩토리 펑션을 이용한다.
  • Express는 익스프레스 앱을 만드는 팩토리이다.

이렇듯, 사실상 제일 알려진 라이브러리와 프레임웍트들은 많이 이용한다. 팩토리 보다 객체 생성에 더많이 생성되는 패턴은 객체리터럴이 유일하다. 자바스크립트의 내장기능들은 컨스트럭처를 사용하면서 시작됬다. 왜냐하면 BrendanEich가 자바스크립트를 자바처럼 보이도록 만들라고 말했기 때문이다. 지금 모든것을 팩토리를 사용하고 컨스트럭처를 사용하지 않기에는 시기상조일것이다.

당신의 API가 구리다는뜻은 아니다.


Q. 프로토타입 상속보다 클래스 상속이 조금 더 관용 적이지 않나?

"아니다"

매번 이런 오해를 들을때마다 나는 이렇게 말하고 싶다 "자바스크립트를 해본적은 있나요?" 당신도 이런 질문을 가지고 있더라도 기분 나빠하지 않았으면 좋겠다. 이건 당신의 잘못이 아니라 자바스크립트 트레이닝이 구린것이니까 이 질문에 대한 답은 크고 거대하다.

아니다...(하지만) 자바스크립트에서 프로토타입은 관용적인 상속 패러디임이고 클래스는 침입하는 종(invasive species)이다.

유명한 자바스크립트 라이브러리들의 간략한 역사

처음엔 모두가 자신만의 라이브러리를 작성했고 공유는 중요한 일이 아니었다. 그러다 Prototype이 등장했다(이름이 힌트다) Prototype은 Concatenative 상속을 이용해서 내장된 위임 프로토타입을 확장하는 방법으로 마법을 부렸다. 이후 네이티브와 충돌을 일으킨 라이브러리가 인터넷을 망쳤을때 내장 위임 프로토타입을 수정하는것은 안티패턴이라는것을 깨닫게 되었다. 다음으로 떠오른 자바스크립트 라이브러리는 jQuery였다. jQuery가 명성을 얻게된것은 플러그인때문이었다. 플러그인들은 concatenative 상속을 이용해 jQuery의 위임 프로토타입을 확장해서 동작했었다.

jQuery는 제일 많이 쓰이는 자바스크립트 라이브러리로 남았다.

이때가 혼란기였고 클래스 확장은 언어로 점점 스며들기 시작했다. 존레식은 Simple Class Inheritance in javascript라는 글을 썼고 사람들은 이것을 실제로 사용하기 시작했었다 비록 존레식 자신은 이것을 jQuery에 넣을 생각을 하지 않았어도 말이다(왜냐하면 프로토타입 상속이 같을일을 더 잘했기 때문이다).

어느정도 알려진 ExtJS와 같은 자바풍의 프레임웍이 나왔고 자바스크립트에서의 클래스사용을 일종의 대세로 이끌었다. 이때가 2007년이었다. 조금 유명한 라이브러리들이 유저에게 클래스 상속을 노출하기 전인 자바스크립트가 12살때 였다. 3년이 지났고 클래스 상속을 흉내낼수 있는 'extend()'메소드를 가진 백본이 튀어나왓고 이것은 다른 지저분한 기능들도 포함하고있었다.(예를들어 Brittle object hierarchies) 이때 지옥이 속박에서 풀려났다.

100k라인의 앱을 백본을 이용하여 개발했다. 몇달이 지난후 나는 버그를 찾으려고 6래밸의 상속구조를 뒤져 디버깅해야했다. super채인을 따라 한라인 한라인 살펴봤고 최상위 클래스에서 버그를 찾았고 수정했었다. 그리고는 베이스 클래스의 행동에 의존하는 많은 자식 클래스들도 수정해야 했다. 5분이면 해결했어야 할 몇시간 동안의 좌절이었다.

이것은 자바스크립트가 아니다. 나는 갑자기 자바 지옥에서 다시 살게 되었다. 그곳은 외롭고, 어둠고 무서운 어떤 빠른 움직임들이 전체의 상속구조를 위협하고 융합을 무너트릴수 있는곳이다.

그런데 Backbone 문서에서 한줄기의 빛을 발견한다

// A ray of sunshine in the belly of
// the beast...

var object = {};

_.extend(object, Backbone.Events);

object.on("alert", function(msg) {
  alert("Triggered " + msg);
});

object.trigger("alert", "an event");

우리의 오랜친구 concatenative 상속은 'Backbone.Events'의 믹스인으로 존재하고 있었다. 어느정도 유명한 자바스크립트 라이브러리를 자세히 살펴보면 concatenation과 delegation의 예시를 찾게 될것이다. 이것은 자바스크립트개발자가 일반적이고 습관적으로 하면서도 상속이라고 생각 조차 하지 않는일이다. 비록 같은 목적을 달성하더라도 말이다.

자바스크립트에서의 상속은 쉽다. 이는 상속에 노력이 필요하기를 원하는 사람들을 혼란시켰고 더 어렵게 만들기위해 우리는 클래스를 추가했다.

그리고 우리는 프로토타입 상속위에서 프로토타입위임과 오브젝트 이어붙이기를 이용해 이를 구현했다. 이것은 Tesla Model S를 자동자매장에 가져가 오래되고 낡은 1983 Ford Pinto와 교환한것과 같다


Q. 상황에 따라서 클래스 상속과 프로토타입 상속을 선택하면 되지 않을까?

"아니다"

Prototypal OO는 간단하고, 더 유연하고 에러를 줄일수있다. 나는 이런 주장을 계속 해왔고 클래스를 쓸수 밖에 없는 케이스를 들고온 사람들과의 논쟁을 수년간 펼쳐왔다. 수백 수천 명의 사람들이 요청을 들었고 내가 받은 몇몇의 대답은 이 아티클이 언급한 오해중 한개 혹은 이상에 의한것이었다.

나는 한때 클래스 상속의 팬이었고 완전히 믿었다. 나는 이곳 저곳에 객체 상속을 구현했다. 나는 시각적인 객체 지향 Rapid Application Development tool들을 만들어 소프트웨어 아키텍트들이 객체의 상속과 관계를 설계하기 쉽게 만들었고 클래스 상속분류법을 이용하는 엔터프라이즈 어플리케이션의 객체들의 관계를 맵과 그래프를 이용하여 시각적으로 보여주는 툴이 포함되어 있었다. 그리고 얼마지나지 않아 나는 C++과 자바에서 자바스크립트로 전환했고 이런 모든것을 그만뒀다. 내가 덜 복잡한 앱을 개발하게 되었기 때문이 아니라(오히려 반대다), 자바스크립트가 훨씬 더 간단 했기 때문에 더이상 그런 객치지향 설계 툴 필요 없어졌기 때문이다.

나는 어플리케이션 설계 컨설팅을 하곤 했는데 자주 광범위한 부분의 재작성을 추천했다. 왜냐면 모든 객체 상속은 결국 새로운 유즈케이스에 맞지 않게 될것이기 때문이다.

나는 혼자가 아니었다. 요즘엔 새로운 버전의 소프트웨어를 위해 전체의 코드를 재작성하는게 일반적인 일이 되었다. 대부분의 이런 재작성은 깨어지기 쉬운 클래스 상속에 의한 레거시 코드들로 인해 필연적이었다. 대부분의 책들이 객체 지향 설계의 실수와 어떻게 실수를 피할수 있는지, 그것들을 피해 리팩토링할지를 다룬다. 모든 개발자들의 책상 마다 디자인 패턴책이 있는것 처럼 보인다.

나는 이부분에 대한 Gang of Four's의 충고를 따르기를 추천한다.

'클래스 상속보다는 객체 조합을 이용해라'

자바에서는 이건 클래스 상속보다 훨씬더 어렵다 왜냐면 실제로 이를 구현하려면 클래스들을 이용해야 하기 때문이다.

자바스크립트에서는 변명의 여지가 없다.

자바스크립트에서는 여러 프로토타입을 서로 조합해 객체를 생성하면 되므로 객체의 계층구조를 관리하는것보다 훨씬 쉽게 구현된다.

예를들어 어떤 Date input도 'megaCalendarWidget'으로 만들수 있는 jQuery 객체를 만든다고 생각해보자 여기서 'extend'나 'class'는 필요 없다. 자바스크립트는 동적 객체 확장을 지원하고 jQuery는 자신의 프로토타입이 외부로 노출이 되어있으니 이를 이용해 확장하면 된다.

/*
How to extend the jQuery prototype:
So difficult.
Brain hurts.
ouch.
*/

jQuery.fn.megaCalendarWidget = megaCalendarWidget;

// omg I'm so glad that's over.

이제 jQuery 팩토리를 통해 만들어지는 인스턴스는 Date input을 Mega Calendar로 만들수 있다.

비슷하게 'Object.assign()'을 이용해서 몇개의 객체라도 조립할수 있다.(last-in 우선순위로)

import ninja from 'ninja'; // ES6 modules
import mouse from 'mouse';

let ninjamouse = Object.assign({}, mouse, ninja);

갯수를 늘려보자

// so this time I'll use Lodash. It's like Underscore,
// with 200% more awesome. You could also use
// jQuery.extend() or Underscore's _.extend()
var assign = require('lodash/object/assign');

var skydiving = require('skydiving');
var ninja = require('ninja');
var mouse = require('mouse');
var wingsuit = require('wingsuit');

// The amount of awesome in this next bit might be too much
// for seniors with heart conditions or young children.
var skydivingNinjaMouseWithWingsuit = assign({}, // create a new object
  skydiving, ninja, mouse, wingsuit); // copy all the awesome to it.

이런 기술은 concatenative 상속 이라고 한다. 당신이 상속하는 프로토타입들은 때론 원형 프로토타입(exemplar prototype)을 참조한다. 이것은 프로토타입 상속과는 다르게 프로토타입에 기능을 위임하는게 아니라 내용을 복사해온다.


Q. ES6은 class라는 키워드를 가지고 있다. 이것은 우리 모두가 이것을 이용하게 될 것이란 뜻이 아닌가?

"아니다"

ES6의 class키워드를 피해야하는 설득력있는 이유가 많이 있고 우선 이것은 자바스크립트에 맞지가 않다.

우린 이미 자바스크립트에 강력하고 이상적인 객체 시스템을 가지고있고 근래 자바스크립트에서 구현된 class의 개념은 제한적이다 (타입정확성과같은 좋은 의미가 아닌 나쁜의미로..) 그리고 이미 오래전 부터 내장되어 있던 멋진 프로토타입 상속 시스템을 어렵게 만든다.

무엇이 정말 자바스크립트를 위해 좋은건지 아는가? 프로토타입 객체 지향(prototypal OO)에 익숙한 프로그래머의 관점에서 프로토타입을 기반으로 구축한 더 나은 추상화나 Sugar이다.

그게 정말 멋질것이다.

♥ Support writer ♥
with kakaopay

크리에이티브 커먼즈 라이선스이 저작물은 크리에이티브 커먼즈 저작자표시-비영리-변경금지 4.0 국제 라이선스에 따라 이용할 수 있습니다.

© Sungho Kim2023