개별 객체 수준에서 객체를 수정하고 발전시키는 능력은 선험적 분류의 필요성을 줄이고 반복적인 프로그래밍 및 디자인 스타일을 장려
프로토타입 프로그래밍은 일반적으로 분류하지 않고 유사성을 활용하도록 선택
결과적으로 설계는 맥락에 의해 평가
프로토 타입 기반 프로그래밍
프로토타입 언어에서는 분류를 우선하지 않습니다. 생성된 객체 위주로 유사성을 정의합니다.
프로토타입기반 프로그래밍은 클래스리스(class-less), 프로토타입 지향(prototype-oriented) 혹은 인스턴스 기반(instance-based) 프로그래밍이라고도 합니다.
프로토타입 기반 프로그래밍은 객체지향 프로그래밍의 한 형태의 갈래로 클래스가 없고, 클래스 기반 언어에서 상속을 사용하는 것과는 다르게, 객체를 원형(프로토타입)으로 하여 복제의 과정을 통하여 객체의 동작 방식을 다시 사용할 수 있습니다.
프로토 타입 객체를 만든 다음 새로운 인스턴스를 만듭니다. 객체는 JavaScript로 변경할 수 있으므로 새로운 인스턴스를 확장하여 새로운 필드와 메소드를 제공 할 수 있습니다. 그러면 더 새로운 객체의 프로토 타입 역할을 할 수 있습니다. 비슷한 객체를 많이 만들기 위해 클래스가 필요하지 않습니다.
프로토 타입 기반 프로그래밍은 프로토 타입 역할을 하는 위임을 통해 기존 객체를 재사용하는 프로세스를 통해 동작 재사용(상속)을 수행 하는 객체 지향 프로그래밍 스타일입니다.
프로토 타입 기반 프로그래밍은 일반화 된 객체를 사용하여 복제 및 확장 할 수 있습니다.
거의 모든 프로토 타입 기반 시스템은 인터프리터이고 동적으로 유형이 지정된 언어를 기반 으로 합니다. 하지만 프로토타입기반의 정적 타입의 체계가 기술적으로 가능합니다.
많은 프로토 타입 기반 시스템은 런타임 동안 프로토 타입 변경을 장려하는 반면, 클래스 기반 객체 지향 시스템을 사용하면 프로그램 실행 중에 클래스를 변경할 수 있습니다.
위임 과정에 대해
JS는 프로토타입 기반 언어의 특징인 위임 과정을 따릅니다.
모든 위임 과정은 런타임 시점에서 이루어집니다.
위임이란 객체들간의 원형 복제 과정을 말합니다.
위임된 객체 원형은 값(value)이 아닌 참조 값(reference of value)을 가집니다.
위임된 객체 원형은 해당 객체의 특징(속성, 메서드)들을 공유하기위해 사용됩니다.
위임받은 자식 객체는 부모 객체의 원형을 참조하고 있기 때문에, 자식 객체로 부터 부모 객체의 원형이 변조될 수 있습니다(이로인해 아주 위험한 상황이 연출될 수 있습니다).
위임 받은 자식 객체는 원하는 특징(속성, 메서드)에 도달하기위해, 각 객체들이 가진 원형을 연속적으로 따라가 찾아내게 됩니다.
또한, 프로토타입 검색 범위는 동적으로 변경될 수 있습니다.
연쇄 과정에 대해
순수 프로토타입은 연쇄적 프로토타입이라고도 합니다.
연쇄란 객체들간의 원형 복제 과정을 말합니다.
연쇄된 객체 원형은 참조 값(reference of value)이 아닌 원본으로부터 복제된 객체 값(value)을 가집니다.
연쇄된 자식 객체는 원본 객체로부터 복제된 원형을 참조하기 때문에, 자식 객체를 통해 원본 객체의 특징들이 변조될 수 없습니다.
연쇄된 자식 객체는 원하는 특징(속성, 메서드)에 도달하기위해, 각 객체들이 가진 원형을 연속적으로 따라가 찾아내게 됩니다.
연쇄 방식의 프로토타입 검색 범위는 정적(연쇄 시점에 의해)으로 고정됩니다.
Concatenation(연쇄) - prototype pattern과 유사해 보임
순수 프로토타입은 연쇄적 프로토타입이라고도 하는데 케보가 그 예입니다. 원본 프로토타입에서 복제된 객체로 포인터는 보이지 않습니다. 프로토타입 객체는 정확히 복사되지만, 다른 이름이나 참조값을 가집니다. 메서드와 속성은 대응되는 것으로 중복된다.
이렇게 접근하면 객체 작성자가 한 부모 객체의 자식 객체들간에 부수효과를 신경쓰지 않고 복제할 수 있다는 이점이 있습니다. 또 다른 이점은, 디스패치 중 메서드 미리보기의 계산 비용이 위임에 비해서 급격히 줄어든다는 것이다. 위임을 하면 적합한 메서드나 슬롯을 찾는 것을 실패한다면 전체 위임 사슬에서 찾아봐야 하기 때문이다.
연쇄 접근 방식의 단점은 시스템을 통해 바뀌는 것을 번식시키는 데에 조직적으로 어렵다는 것이다. 프로토타입에 변화가 생기면 이것은 복제품에 즉시 혹은 자동적으로 적용되지 않습니다. 그러나 케보는 위임 방식에서 주로 쓰는 분류상의 원형을 사용하지 않고, 추가적인 기본형을 제공하여 가족 닮음(family reseemblances)라고 하는 유사한 객체들을 모아서 변화를 적용합니다.
다른 단점은 이 형태를 세련되게 구현하지 못하면 원형과 복제품이 같은 부분에서 복제품들이 위임 형태에 비해서 메모리가 더 많이 낭비된다는 것입니다. 그러나 케보에서 실제로 하고 있는 접근 방식처럼 공유하도록 구현하고 자료는 배후에 두는 방식으로 프로그래밍에 대한 연쇄적 행동이 가능합니다.
비평
프로토 타입 기반 시스템을 비판하는 클래스 기반 객체 모델의 옹호자들은 종종 프로그래밍 언어를 위한 정적 타입 시스템의 지지자들이 다이나믹 타입 시스템을 가지고 있다는 우려와 유사한 우려를 가지고 있습니다. 일반적으로 이러한 우려에는 정확성, 안전성, 예측 가능성, 효율성 및 프로그래머의 친숙함이 포함됩니다.
효율성과 관련하여 클래스를 선언 하면 효율적인 메서드 및 인스턴스 변수 조회를 개발할 수 있는 많은 컴파일러 최적화가 단순화 됩니다.
프로토 타입 기반 언어에 대한 일반적인 비판은 JavaScript의 인기와 시장 침투에도 불구하고 소프트웨어 개발자 커뮤니티가 익숙하지 않다는 것입니다. 프로토 타입 기반 시스템의 지식 수준은 JavaScript 프레임 워크의 확산과 웹이 성숙함에 따라 JavaScript의 복잡한 사용과 함께 증가하고 있습니다.
ECMAScript6은 JavaScript의 기존 프로토타입 기반 상속에 대한 구문 설탕으로 클래스를 도입하여 객체를 생성하고 상속을 처리하는 대체 방법을 제공합니다.
클래스 기반과의 비교
클래스기반 언어에서 객체는 일반적으로 두 가지 형태가 있습니다. 클래스는 객체의 기본적인 만듦새와 기능을 정의하고, 인스턴스는 '사용할 수 있는' 객체로 특정 클래스의 양식을 기반으로 합니다. 클래스 기반 언어에서 ‘클래스’는 동작 방식인 메소드의 모임으로 동작하고, 모든 인스턴스의 구조는 동일하고, 인스턴스는 객체의 자료를 가지고 있습니다. 한쪽에는 구조와 동작 방식, 다른 한쪽에는 상태로 구분된다.
프로토타입 기반 프로그래밍을 지지하는 사람들은 클래스 기반 언어에서는 개발자가 클래스들 사이의 분류와 관계에 먼저 초점을 맞추기 쉽다고 합니다. 이와는 달리, 프로토타입기반 프로그래밍은 프로그래머가 여러 가지 표본의 동작 방식에 초점을 맞추고, 이 객체들을 나중에 클래스와 비슷한 방식의 객체의 원형으로 분류하는 것은 나중에 걱정해도 됩니다.
많은 프로토타입기반 체계가 실행시간에 프로토타입을 대체하기 쉬우나, 클래스기반 객체지향 체계에서는 최초의 동적 객체지향 체계인 스몰토크와 같이 프로그램의 실행 중에 클래스를 바꿀 수 있는 것은 몇 가지 되지 않습니다.
객체 생성
클래스기반 언어에서, 클래스의 생성자를 통하거나 필요하다면 생성자와 생성자의 매개변수를 통하여 인스턴스를 새로 만듭니다. 결과로 만들어진 인스턴스는 선택된 클래스의 설계와 행동을 따르게 됩니다.
프로토타입기반 체계에서, 새 객체를 만드는 세 가지 방법이 있습니다.
첫번째는 Object 생성자 함수를 사용하는 방법입니다.
두번째는 원래 있던 객체를 복제(cloning)하는 방법입니다. 객체 리터럴 방식으로 생성된 객체는 결국 내장 함수(Built-in)인 Object 생성자 함수로 객체를 생성하는 것을 단순화시킨 것입니다.
세번째는 ‘무(無)에서’ 객체를 생성하는 방법입니다. 대부분 다양한 복제 방식을 제공하기 때문에, 무에서 객체를 생성하는 것은 흔하지 않습니다.
무에서 객체를 생성할 수 있는 체계는 이미 있던 프로토타입을 복제하지 않고 아무것도 없는 상태에서 새로운 객체를 생성할 수 있게 해 줍니다. 이런 체계는 새 객체의 특성과 행동을 이미 있던 객체를 참조하지 않고도 지정할 수 있습니다. 많은 프로토타입기반 언어에서 기본 객체 프로토타입인 Object 프로토타입이 있는데, 여기에 공통적으로 필요한 메서드가 들어있고, 모든 객체의 마스터 프로토타입으로 사용됩니다. 무에서 객체를 창조하는 방식은 새 객체의 슬롯 이름이 최상위의 Object 객체와 네임스페이스 충돌이 일어나지 않게 하는 것입니다. 모질라 자바스크립트는 객체의 __proto__ 프로퍼티를 null로 지정하면 이것이 가능하도록 구현되어 있습니다.
복제는 원래 있던 객체의 프로토타입의 행동을 복제하여 새 객체를 생성하는 과정을 거칩니다. 새 객체는 원본의 모든 특성을 가집니다. 이 상태에서 새 객체를 수정할 수 있습니다. 어떤 체계에서 복제된 자식 객체는 명시적으로 프로토타입과 위임(delegation)이나 닮음(resemblance)으로 연관되어 있습니다. 그래서 프로토타입을 변경하면 복제품에 영향을 끼칩니다. 포스와 케보 같은 다른 체계에서는 프로토타입을 번식시키는 이런 방식을 따르지 않고, 대신에 프로토타입을 수정하더라도 복제품에는 영향을 끼치지 않는 연쇄된 형태를 사용하여 원본 객체를 수정하더라도 그 자손으로 자동 번식되지 않습니다(프로토타입 패턴과 유사)
// 원형 객체가 없는 상태에서 객체를 생성하는 방법(일부 브라우저를 통해 아래와 같은 무형 객체를 구현할 수 있습니다)var instance ={};
instance.__proto__ =null;
console.dir(instance);// Object
console.log(typeof instance);// object
Delegation
실행시간에 위임하는 프로토타입기반의 언어들은 올바른 메서드로 동적 디스패치를 할 수 있거나, 맞는 자료 조각에 이를 때까지 객체에서 프로토타입으로 간단히 위임 포인터를 연속적으로 따라가서 찾을 수 있습니다.
객체들 사이에서 동작을 공유하는 것을 확립하기 위해 필요한 것들은 위임 포인터뿐입니다.
클래스기반 객체지향 언어에서 클래스와 인스턴스의 관계와 달리 프로토타입과 파생된 객체는 이 연결을 통하여 프로토타입과 자식 객체가 메모리나 구조적인 유사성을 가질 필요가 없습니다. 마찬가지로, 자식 객체는 클래스 기반의 연관된 클래스의 구조를 재배치하지 않고 계속해서 수정할 수 있습니다. 또 중요한 점은, 자료뿐만 아니라 메서드도 추가되거나 변경될 수 있다는 것입니다. 이런 이유로 대부분의 프로토타입기반 언어들은 데이터와 메서드 두가지 모두 슬롯으로 관리합니다.
부가정보
클래스 기반 언어와 프로토타입 기반언어의 차이
클래스 기반 언어
클래스 기반 언어에서는, 객체의 형식이 정의된 클래스라는 개념을 가집니다.
클래스 기반 언어만의 상속 개념을 가집니다.
프로토타입 기반 언어
프로토타입 기반 언어에서는 클래스라는 개념이 존재하지 않으며, 여러 종류의 Built-in 객체들이 시스템상에 존재하게 됩니다. 또한 클래스 기반언어의 상속 개념과 달리, 객체 원형의 위임 과정을 통해 상속 과정이 구현됩다.
일반적으로 프로토타입 기반 언어는 클래스가 존재하지 않습니다.
클래스 기반 언어는 보통 정적 언어를 말하며, JS와 같은 동적 언어는 컴파일 시점이 아닌 런타임 시점에서 정적 언어가 다루는 특정 일(자료형 검사, 함수 오버로드, 동적 디스패치 등)들을 수행합니다.
정적/동적 언어란?
정적언어
컴파일 시점에서 자료형 검사가 이루어집니다.
컴파일 시점의 자료형 검사로 인해 런타임 시점에서는 자료형에 대한 많은 오류를 줄일 수 있습니다(단 컴파일 시점에서 결정될 수 있는 자료형 정보만이 평가(검사)됩니다).
컴파일 시점에서의 자료형 검사를 반복할 필요가 없기 때문에, 전체 프로그램 실행 시간이 줄어듭니다.
동적언어
런타임 시점에서 자료형 검사가 이루어집니다.
런타임 시점의 자료형 검사로 인해 자료형에 대한 런타임 오류가 발생할 수 있습니다.
모든 런타임 객체가 자료형에 대한 정보를 가지고 있으며, 이를 통해 함수 오버로드, 동적 디스패치 등을 수행할 수 있습니다(동적 언어가 가지는 유연성).
변수는 모든 자료형을 가질 수 있다.
자바스크립트는 느슨한 타입(loosely typed) 언어, 혹은 동적(dynamic) 언어입니다. 그 말은, 변수의 타입을 미리 선언할 필요가 없다는 뜻입니다. 타입은 프로그램이 처리되는 과정에서 자동으로 파악될 것입니다. 또한 그 말은 같은 변수에 여러 타입의 값을 넣을 수 있다는 뜻입니다.