전에 배운 모든 객체 지향 지식을 잊어 버리십시오. 여기서 경주 상황을 고려하십시오. 예, 경주입니다.
최근에 나는 프랑스에서 인기있는 행사 인 Le Mans의 24 시간을보고 있습니다. 가장 빠른 자동차를 Le Mans 프로토 타입이라고합니다. 이 자동차는 "Audi"또는 "Peugeot"과 같은 제조업체에 의해 만들어 지지만 거리 나 고속도로에서 볼 수있는 자동차는 아닙니다. 고속 지구력 이벤트를 위해 특별히 만들어집니다.
제조업체는 이러한 프로토 타입 자동차를 개발, 설계 및 제조하기 위해 엄청난 양의 돈을 투자하며 엔지니어는 항상이 프로젝트를 극단적으로 만들려고 노력합니다. 그들은 합금, 바이오 연료, 제동 기술, 복합 조성 및 타이어의 안전성에 대한 다양한 실험을 수행했습니다. 시간이 지남에 따라,이 실험의 일부 기술은 반복적으로 개선되었으며 주류 제품 라인에 들어갔다. 운전중인 차량의 일부 기술은 레이싱 프로토 타입에서 데뷔했을 수 있습니다.
또한이 주류 차량은 경주 용 자동차의 기술 프로토 타입을 물려받을 수 있습니다.
지금까지 우리는 JavaScript의 프로토 타입 및 상속 문제를 논의하기위한 기초가 있습니다. C ++, Java 또는 C#에서 알고있는 클래식 상속 패턴만큼 좋지는 않지만 강력하고 잠재적으로 더 유연합니다.
JavaScript는 객체로 가득 차 있는데, 이는 전통적인 의미의 대상, 즉 "상태와 행동을 포함하는 단일 엔티티"를 나타냅니다. 예를 들어, JavaScript의 배열은 여러 값을 포함하고 푸시, 리버스 및 팝 메소드를 포함하는 객체입니다.
var myArray = [1, 2]; myArray.push (3); myArray.reverse (); myArray.pop (); var length = myArray.length;
이제 문제는 푸시가 어디에서 왔습니까? 앞에서 언급 한 정적 언어는 객체의 구조를 정의하기 위해 "클래스 구문"을 사용하지만 JavaScript는 "class 구문"이없는 언어이며 배열 "클래스"의 구문을 사용하여 각 배열 객체를 정의 할 수 없습니다. JavaScript는 역동적 인 언어이므로 실제로 필요한 대상에 메소드를 배치 할 수 있습니다. 예를 들어, 다음 코드는 2 차원 공간의 점을 나타내는 데 사용되는 포인트 객체를 정의하고 추가 방법을 정의합니다.
var point = {x : 10, y : 5, add : function (기타 점) {this.x += OtherPoint.x; this.y += OtherPoint.y; }};그러나 위의 관행은 그다지 확장 가능하지 않습니다. 각 포인트 객체에 ADD 메소드가 포함되어 있는지 확인해야하며,이 메소드를 각 포인트 객체에 수동으로 추가하는 대신 모든 포인트 객체가 동일한 추가 방법의 구현을 공유하기를 원합니다. 프로토 타입이 작동하는 곳입니다.
JavaScript에서 각 객체는 숨겨져 있습니다. 프로토 타입이라고도하는 다른 객체에 대한 참조입니다. 우리가 만든 배열은 프로토 타입 객체를 참조하고 우리가 만든 포인트 객체도 마찬가지입니다. 위에서 언급했듯이 프로토 타입 참조는 숨겨져 있지만 객체의 __proto__ 속성 (예 : Chrome)을 통해이 프로토 타입 참조에 액세스 할 수있는 ecmascript (JavaScript의 공식 이름)도 구현됩니다. 개념적으로, 우리는 객체를 그림 1 프로토 타입에 표시된 것과 유사한 관계로 취급 할 수 있습니다.
그림 1
앞으로, 개발자는 객체 프로토 타입에 대한 참조를 얻기 위해 __proto__ 속성 대신 Object.GetPrototype 함수를 사용할 수 있습니다. 이 기사를 작성할 때 Object.getPrototype 기능은 이미 Google Chrome, Firefox 및 IE9 브라우저에서 사용할 수 있습니다. 더 많은 브라우저는 이미 ECMAScript 표준의 일부이기 때문에이 기능을 향후이 기능을 구현할 것입니다. 우리는 다음 코드를 사용하여 우리가 만든 MyArray 및 DOT 객체가 두 개의 다른 프로토 타입 객체를 참조한다는 것을 증명할 수 있습니다.
이 기사의 나머지 부분에서는 __proto__가 그래프와 문장에서 식별하기가 더 쉽기 때문에 __proto__ 및 object.getPrototype 기능을 교차 사용합니다. 그것 (__proto__)은 표준이 아니며 객체 가 객체 프로토 타입을 보는 것이 권장되는 방법입니다.
프로토 타입을 특별하게 만드는 것은 무엇입니까?
우리는이 질문에 대답하지 않았습니다. 배열의 푸시는 어디에서 왔습니까? 대답은 : MyArray 프로토 타입 객체에서 나온 것입니다. 그림 2는 Chrome에서 스크립트 디버거의 스크린 샷입니다. MyArray의 프로토 타입 객체를보기 위해 Object.getPrototype Method를 호출했습니다.
그림 2
MyArray의 프로토 타입 객체에는 코드 예제에서 Push, Pop 및 Reverse Methods라는 방법을 포함하여 많은 방법이 있습니다. 따라서 푸시 방법에는 프로토 타입 객체가 포함되지만 MyArray 메소드는 어떻게 참조합니까?
myarray.push (3);
그것이 어떻게 작동하는지 이해하는 첫 번째 단계는 프로토 타입이 특별하지 않다는 것을 깨닫는 것입니다. 프로토 타입은 정상적인 물체 일뿐입니다. 방법, 속성을 프로토 타입에 추가하여 다른 JavaScript 객체로 취급 할 수 있습니다. 그러나 George Orwell의 소설 "Animal Farm"에 "Pig"의 진술을 적용하려면 모든 대상은 동일해야하지만 일부 대상 (규칙을 따르는 사람들)은 다른 물체보다 동일합니다.
JavaScript의 프로토 타입 객체는 다음 규칙을 따르기 때문에 실제로 특별합니다. javaScript에 객체의 푸시 메소드를 호출하거나 객체의 X 속성을 읽으려면 런타임이 먼저 객체 자체를 찾습니다. 런타임이 원하는 것을 찾을 수없는 경우 __proto__ 참조 및 객체 프로토 타입을 따라 멤버를 찾습니다. MyArray의 푸시 메소드를 호출 할 때 JavaScript는 MyArray 객체에서 푸시 메소드를 찾지 못하지만 MyArray의 프로토 타입 객체에서 JavaScript 가이 방법을 호출합니다 (그림 3 참조).
그림 3
위에서 설명한 동작은 프로토 타입의 방법이나 속성을 상속하는 물체 자체를 나타냅니다. JavaScript에서는 클래스 구문을 사용하지 않고 실제로 상속이 달성됩니다. 레이싱 프로토 타입에서 해당 기술을 상속하는 자동차와 마찬가지로 JavaScript 객체는 프로토 타입 객체에서 기능적 기능을 상속받을 수 있습니다.
그림 3은 또한 각 배열 객체가 자체 상태 및 멤버를 유지할 수 있음을 보여줍니다. MyArray의 길이 속성을 요청할 때 JavaScript는 프로토 타입의 해당 값을 읽지 않고 MyArray에서 길이 속성의 값을 얻습니다. 푸시와 같은 메소드를 객체에 추가하여 푸시 메소드를 "덮어 쓰기"할 수 있습니다. 이것은 프로토 타입에서 푸시 메소드 구현을 효과적으로 숨길 것입니다.
JavaScript에서 프로토 타입의 진정한 마법은 여러 객체가 동일한 프로토 타입 객체에 대한 참조를 유지하는 방법입니다. 예를 들어, 다음과 같은 두 개의 배열을 만드는 경우 다음과 같습니다.
var myarray = [1, 2]; var yourray = [4, 5, 6];
이 두 배열은 동일한 프로토 타입 객체를 공유하고 다음 코드는 true로 평가됩니다.
Object.getPrototype (MyArray) === Object.getPrototypof (YourArray);
두 배열 객체의 푸시 메소드를 참조하면 JavaScript는 프로토 타입에서 공유되는 푸시 메소드를 찾습니다.
그림 4
JavaScript의 프로토 타입 객체는 상속 기능을 제공하며 동시에이 방법의 공유가 구현됩니다. 프로토 타입도 묶여 있습니다. 다시 말해, 프로토 타입 객체는 객체 일 뿐이므로 하나의 프로토 타입 객체를 다른 프로토 타입 객체에 대한 참조로 유지할 수 있습니다. 그림 2를 다시 방문하면 프로토 타입의 __proto__ 속성이 다른 프로토 타입을 가리키는 널 값이 아닌 값임을 알 수 있습니다. JavaScript는 푸시 메소드와 같은 멤버를 찾으면 프로토 타입 참조 체인을 따라 각 객체가 발견 될 때까지 확인하거나 프로토 타입 체인의 끝에 도달합니다. 프로토 타입 체인은 상속 및 공유를위한 유연한 경로를 열어줍니다.
다음 질문은 다음과 같습니다. 해당 사용자 정의 객체에 대한 프로토 타입 참조를 어떻게 설정합니까? 예를 들어, 이전에 사용 된 포인트 객체는 프로토 타입 객체에 추가 메소드를 추가하고 여러 포인트 객체에서 메소드를 상속 할 수있는 방법은 무엇입니까? 이 질문에 대답하기 전에 기능을 살펴 봐야합니다.
JavaScript의 함수도 객체입니다. 이러한 진술은 몇 가지 중요한 결과를 가져 오며이 기사의 모든 문제를 다루지는 않습니다. 그중에서도 변수에 함수를 할당하고 매개 변수로 함수를 다른 함수로 전달하는 능력은 현대 JavaScript 프로그래밍 표현식의 기본 패러다임을 구성합니다.
우리가주의를 기울여야 할 것은 함수 자체가 객체이므로 함수는 고유 한 메소드, 속성 및 프로토 타입 객체를 참조 할 수 있다는 것입니다. 다음 코드의 의미에 대해 논의 해 봅시다.
// 이것은 true : typeof (array) === "function"// 그러한 표현식이기도합니다 : Object.getPrototypo (array) === 객체 (function () {}) // 그러한 표현식은 다음과 같습니다.코드의 첫 번째 줄은 JavaScript의 배열이 함수임을 증명합니다. 배열 함수를 호출하여 새 배열 객체를 만드는 방법을 볼 수 있습니다. 다음 줄의 코드 라인은 배열 객체가 다른 기능 객체와 동일한 프로토 타입을 다른 기능 객체와 동일한 프로토 타입과 동일한 프로토 타입과 동일한 프로토 타입과 동일한 프로토 타입과 동일한 프로토 타입과 동일한 프로토 타입과 사용한다는 것을 증명합니다. 마지막 코드 줄은 배열 함수에 프로토 타입 속성이 있음을 증명 하고이 프로토 타입 속성은 유효한 객체를 가리 킵니다. 이 프로토 타입 속성은 매우 중요합니다.
JavaScript의 각 기능 객체에는 프로토 타입 속성이 있습니다. 이 프로토 타입 속성의 __proto__ 속성을 혼동 하지 마십시오 . 그것들은 다른 목적을 가지고 있으며 같은 대상을 가리키지 않습니다.
// trueObject.getPrototype (array)! = array.prototype를 반환합니다
배열 .__ proto__는 배열 프로토 타입을 제공합니다. 배열 함수에 의해 상속 된 물체로 취급하십시오.
Array.protoype는 모든 배열에 대한 프로토 타입 객체를 제공합니다. 즉, MyArray와 같은 배열 객체의 프로토 타입 객체를 제공하며 모든 배열이 상속되는 메소드도 포함되어 있습니다. 우리는이 사실을 증명하기 위해 몇 가지 코드를 작성할 수 있습니다.
// truearray.prototype == Object.getPrototypo (MyArray) // 또한 truearray.prototype == Object.getPrototypo (YourArray);
우리는이 새로운 지식을 사용하여 이전 다이어그램을 다시 칠할 수 있습니다.
그림 5
당신이 아는 것에 기초하여, 새 객체를 만들고 새로운 객체가 배열처럼 행동하게 만드는 과정을 상상해보십시오. 한 가지 방법은 다음 코드를 사용하는 것입니다.
// 새 빈 개체 생성 var o = {}; // 동일한 프로토 타입에서 상속 된 배열 객체 O .__ proto__ = array.prototype; // 이제 배열의 모든 메소드를 호출 할 수 있습니다 ... O.push (3);이 코드는 흥미롭고 작동하지만 문제는 모든 JavaScript 환경이 쓰기 가능한 __proto__ 객체 속성을 지원하는 것은 아닙니다. 다행히 JavaScript에는 객체를 만드는 표준 메커니즘이 있습니다. 하나의 연산자 만 새 개체를 만들고 새 개체의 __proto__ 참조, 즉 "새로운"연산자를 설정하면됩니다.
var o = new Array (); O.push (3);
JavaScript의 새 연산자에는 세 가지 기본 작업이 있습니다. 첫째, 새로운 빈 개체를 만듭니다. 다음으로, 새로운 객체의 __proto__ 속성을 설정하여 호출 된 함수의 프로토 타입 속성과 일치합니다. 마지막으로, 연산자는 기능을 호출하여 새 개체를 "이"참조로 전달합니다. 마지막 두 줄의 코드를 확장하려면 다음과 같은 상황이됩니다.
var o = {}; o .__ proto__ = array.prototype; array.call (o); o.push (3);함수의 호출 메소드를 사용하면 함수를 호출 할 때 함수 내부에서 "this"로 참조 된 객체를 지정할 수 있습니다. 물론,이 기능의 저자는이 경우 이러한 함수를 구현해야합니다. 저자가 그러한 함수를 생성하면 생성자라고 할 수 있습니다.
건설자
생성자는 일반 기능과 동일하지만 다음 두 가지 특성이 있습니다.
배열은 생성자의 예입니다. 배열 함수는 새 연산자와 함께 사용해야하며 초기 배열 문자는 대문자입니다. JavaScript에는 내장 기능으로 배열이 포함되어 있으며 누구나 자신의 생성자를 작성할 수 있습니다. 실제로, 우리는 마침내 이전에 생성 된 포인트 객체에 대한 생성자를 작성할 수 있습니다.
var point = function (x, y) {this.x = x; this.y = y; this.add = function (OtherPoint) {this.x += OtherPoint.x; this.y += OtherPoint.y; }} var p1 = new Point (3, 4); var p2 = new Point (8, 6); p1.add (p2);위의 코드에서는 새 연산자와 포인트 함수를 사용하여 x 및 y 속성과 추가 메소드를 갖는 포인트 객체를 구성합니다. 그림 6과 같이 최종 결과를 상상할 수 있습니다.
그림 6
문제는 이제 각 포인트 객체에 별도의 추가 메소드가 여전히 있다는 것입니다. 우리가 배운 프로토 타입과 상속을 사용하여 각 점 인스턴스의 포인트 객체의 추가 메소드를 point.prototype로 전송합니다. 추가 방법을 상속하는 효과를 얻으려면 포인트를 수정하는 것입니다.
var point = function (x, y) {this.x = x; this.y = y;} point.prototype.add = function (OtherPoint) {this.x += OtherPoint.x; this.y += OtherPoint.y;} var p1 = new Point (3, 4); var p2 = new Point (8, 6); p1.add (p2);임무가 완료되었습니다! 방금 JavaScript에서 프로토 타입의 상속 모드를 완료했습니다!
그림 7
요약
이 기사가 JavaScript 프로토 타입 개념의 미스터리를 발견하는 데 도움이되기를 바랍니다. 처음에 본 것은 프로토 타입이 객체가 다른 객체에서 기능을 상속 할 수 있도록 허용 한 다음 새 연산자와 생성자를 결합하여 객체를 구축하는 방법을 보았습니다. 여기에 언급 된 것은 객체 프로토 타입의 전원과 유연성을 잠금 해제하는 첫 번째 단계 일뿐입니다. 이 기사에서는 프로토 타입 및 JavaScript 언어에 대한 새로운 정보를 직접 발견하고 배우도록 권장합니다.
또한 조심스럽게 운전하십시오. 당신은 도로에서 여행하는이 차량들이 프로토 타입에서 상속 될 (결함이있는) 기술을 결코 알지 못할 것입니다.
원본 링크 : 스크립트 중독자 번역 : Bole Online -Emje