2009-11-09 3 views
7

OO 자바 스크립트에서 누군가가 function.prototype의 thingie (thingie !! ??)를 설명 할만큼 충분히 친절한 지 궁금합니다. 다음 코드 조각을 감안할 때누군가가 javascript prototypal inheritance를 설명 할 수 있습니까

내가 서버 측 프로그래밍 배경에서 오는, 나는 프로토 타입의 전체 개념을 파악하고 있지 않다있을 수

:

var animate=function(){}; 
animate.angular=function(){/*does something here*/}; 
animate.circular=function(){/*does something here*/}; 

그리고

var animate=function(){}; 
animate.prototype.angular=function(){/*does something here*/}; 
animate.prototype.circular=function(){/*does something here*/}; 

까지 내가 말할 수있는 바와 같이 후자의 함수는 모두 animate.angular(/*args*/)animate.circular(/*args*/)을 통해 호출 할 수 있습니다. 제 질문은 무엇입니까? 두 번째 방법으로 함수를 정의하는 것? 어떻게 또는 왜 다른가? 희망은 내가 감각을 만들어

...

편집 :는, 그것은 "올바른"로서 여기에 대한 답을 판단하는 것은 매우 어려운 계몽 답변을 전부 감사합니다, 그래서 내가 느끼는 한 거을 ​​표시 해주고있어 가장 기여 ... 당신 모두가 확실히 나에게 생각을위한 음식을 더 준

...

+3

프로토 타입 상속 (특히 wrt JavaScript)에 대해 설명하는 또 다른 멋진 대답은 다음과 같습니다. http://stackoverflow.com/questions/1595611/how-to-properly-create-a-custom-object-in-javascript/1598077 # 1598077 –

+2

관련 링크 : http://stackoverflow.com/questions/186244/what-does-it-mean-that-javascript-is-a-prototype-based-language –

답변

6

나는 당신이 당신의 예를 어딘가에 새로운 애니메이션 (동일 뭔가)을 설정하는 의미 생각합니다. 새로운을 사용하지 않고 내가 무슨 일에 약간의 정교한 것이다 :

var animate = function(){ console.log(0, 'animate'); }; 
animate.angular = function(){ console.log(1, 'animate.angular'); }; 
animate.circular = function(){ console.log(2, 'animate.circular'); }; 

animate.prototype.angular = function(){ console.log(3, 'animate.prototype.angular'); }; 
animate.prototype.circular = function(){ console.log(4, 'animate.prototype.circular'); }; 

첫 번째 두 가지 기능 # 1 & # 2의 애니메이션 변수에서 호출 할 수 있습니다.

animate.angular(); 
animate.circular(); 

당신이 새로운 애니메이션()를 작성하는 경우 당신이 다음 두, # 3 & # 4, 호출 할 수 있습니다 (하지만 # 1 또는 # 2).

var ani2 = new animate(); 

ani2.angular(); 
ani2.circular(); 

또한 animate()는 함수이지만 ani2는 그렇지 않습니다.

console.log(5, typeof animate); 
console.log(6, typeof ani2); 
console.log(7, animate()); 

ani2는 이미 생성되었지만 animate.prototype을 통해 새 구성원을 추가 할 수 있습니다.

animate.prototype.bark = function(){ console.log(8, 'bark'); }; 
ani2.bark(); 

animate 변수는 프로토 타입 형식을 상속받지 않습니다. 회원을 상속하지 않습니다 ani2가 애니메이션 변수에 직접 적용하는 것이

console.log(9, typeof ani2.bark); 
console.log(10, typeof animate.bark); 

참고. animate.prototype에서만 상속을받습니다.

animate.paperclip = function(){ console.log(11, "paperclip"); }; 

animate.paperclip(); 
console.log(12, typeof ani2.paperclip); 
console.log(13, typeof animate.paperclip); 

또한 새로운 아이들에게 인스턴스 멤버를 추가하는 애니메이션과 같은 생성자 함수 내부하여 키워드를 사용할 수 있습니다. 이 수정 된 때문

var Anime = function(a,b){ this.a=a; this.b=b; this.c=console; }; 
var anime1 = new Anime(14, 'anime1'); 
var anime2 = new Anime(15, 'anime2'); 
anime1.c.log(anime1.a, anime1.b); 
anime2.c.log(anime2.a, anime2.b); 

Anime.prototype.a = 16; 
Anime.prototype.z = 'z'; 

var anime3 = new Anime(17, 'anime3'); 
anime3.c.log(18, anime3.a, anime3.b, anime3.z, " ", anime2.a, anime2.b, anime2.z, " ", anime1.a, anime1.b, anime1.z); 
anime2.z='N'; 
anime3.c.log(19, anime3.a, anime3.b, anime3.z, " ", anime2.a, anime2.b, anime2.z, " ", anime1.a, anime1.b, anime1.z); 

메모리가 자동으로 anime2.z의 별도의 인스턴스에 할당 된, anime1 & anime3 여전히 '공유'알뜰 수정되지 않은 Z.

a, b 및 c 멤버는 같은 방식으로 "공동"이 아닙니다. 그들은 즉시 생성자에 new Anime() (Anime.prototype에서 상속받지 않음)을 사용하여 할당되었습니다. 또한 프로토 타입의 멤버는 항상 생성자에 의해 "개별화"됩니다.

새로운 키워드를 잊지 마십시오. 그렇지 않으면 아무 것도 작동하지 않습니다. 예를 들어, 없이 호출 된 생성자의 전역 개체를 가리 킵니다.

console.log(20, typeof window.a, typeof window.b, typeof window.c); 
var opps = Anime(21, 'zapp'); 
console.log(22, typeof window.a, typeof window.b, typeof window.c); 
console.log(23, typeof opps); 

다음은 출력 결과입니다. 그리고 Tom이 Douglas Crockford 비디오를 제안하는 데는 두 번째입니다!


/* 
1 animate.angular 
2 animate.circular 
0 animate 
3 animate.prototype.angular 
4 animate.prototype.circular 
5 function 
6 object 
0 animate 
7 undefined 
8 bark 
9 function 
10 undefined 
11 paperclip 
12 undefined 
13 function 
14 anime1 
15 anime2 
18 17 anime3 z 15 anime2 z 14 anime1 z 
19 17 anime3 z 15 anime2 N 14 anime1 z 
20 undefined undefined undefined 
22 number string object 
23 undefined 
*/ 
+0

당신이 사용하고있는 널리 사용되는 규칙은 constructor-function에 대문자의 첫 글자를 쓰는 것이다. 이것은 new 키워드를 잊어 버리지 않는 데 도움이된다. 프로토 타입 상속에 대한 좋은 기사는 다음에서 찾을 수 있습니다. http://msdn.microsoft.com/en-us/magazine/ff852808.aspx –

2

자바 스크립트가 강한 다른 언어에 비해 구성하는 모든 매우 강력하지만 이상한 언어는 ...했다 .. .

프로토 타입은 클래스의 여러 인스턴스를 생성하려는 경우 JavaScript로 메모리를 절약 할 수있는 방법입니다 ... 따라서 OOP 방식으로 JS를 사용하는 경우 함수를 프로토 타입의 일부로 정의해야합니다. 또한 프로토 타입을 사용하여 상속을 시뮬레이션하는 방법이 있습니다.

책에 대한 좋은 설명이 많은 경우 "Javascript, the Good Parts" 책을 적극 추천합니다.

+0

Google Tech Talk of the 동일한 이름 : http://www.youtube.com/watch?v=hQVTIJBZook 오늘 시청하셨습니다. –

+1

@ gunderson : "이상한"은 매우 주관적인 표현입니다. 6 개월 동안 JS를 제대로 배우고 나면 Java 또는 C++을 사용하는 것보다 더 유창하고 자연스럽게 프로그래밍 할 수 있습니다. 그러므로 나는 너와 동의 할 수 없다. –

+0

이것이 내가 mootools를 좋아하는 이유입니다. 자바 스크립트 상속을 내가 좋아하는 스타일로 보여줍니다. –

2

시간이 3 시간이라면 YUI Theater의 "The JavaScript Programming Language"비디오를 살펴 보시기 바랍니다. 연사/선생님은 더글러스 크로 포드 (Douglas Crockford)입니다. JS는 여러분이 구축 할 수있는 굳건한 JS 기반을 제공 할 것입니다. 이 수업을하지 않는 자바 스크립트 때때로 그런 식으로, 느낌, 그러나 프로토 타입와 함께 작동하더라도

감사

3

. 프로토 타입을 정의한 다음 프로토 타입의 복사본을 만들 수 있습니다.

시작 :

var animate=function(){}; 
animate.angular=function(){/*does something here*/}; 

을 수행 할 수 있습니다

var a = new animate(); 
animate.angular();  // OK 
a.circular();   // error: a.circular is not a function 

그러나, 당신은으로 시작하는 경우 : 지금

function animate(i){}; 
animate.prototype.angular = function() {}; 

할 수 있습니다

var a = new animate(); 
a.angular(); 
,

물론 이것은 인스턴스 변수가 있으면 더 흥미 롭습니다.

function animate(i) { 
    this.x = i; 
} 
animate.prototype.angular = function() { 
    this.x *= 2; 
} 

var a = new animate(5); 
a.angular(); 
console.log(a.x); // 10 
2

프로토 타입 기반 OOP는 자유를 제공합니다. 고급 OOP는 아닙니다.

많은 사람들처럼 Crockford의 설명을 읽으면 실제로 더 배우기를 원한다면 그보다 나은 리소스를 얻을 수 없습니다.

당신은 빠른 혜택을 원하는 경우 :이 너무 불쾌한처럼 (클래스가 다른 언어로 무엇을 나타냅니다)

var Building = function() { 
    this.openDoor = function() {}; 
}; 

var House = function() { 
    this.closeDoor = function() {}; 
}; 
House.prototype = new Building(); 

var a = new House(); 
a.openDoor(); 
a.closeDoor(); 

정의 오브젝트를, 그래서 나는 내 대답에 약간의 팁이 포함됩니다 :

시스템을 구축 할 수

가장 좋은 방법은, 예를 들어, 당신이 선택한 글로벌 네임 스페이스 아래 :

if (typeof MYAPP === 'undefined' || !MYAPP) { 
    var MYAPP = {}; 
} 

function New(className, classBody) { 
    // This adds your "classes" to this MYAPP namespace so they can be instantiated 
    // You need some magic here, so have fun with this function 
} 

New('Building', function() { 
    this.openDoor = function() {}; 
}); 

New('House', function() { 
    this.prototype = new MYAPP.Building(); 
    this.closeDoor = function() {}; 
}); 

// Now you can do the same as before but your application is cleaner :) 
var a = new MYAPP.House(); 
a.openDoor(); 
a.closeDoor(); 

건배.

관련 문제