2013-04-08 2 views
3

저는 JavaScript를 처음 사용합니다 (이번 주에 학습 시작). 나는 CodeCademy 과정을 마치고 (실제로는 객체 1 & &, 나머지는 지루했다). 나는 건축가들과 함께 프로토 타입 상속을 배웠다고 생각했지만, 내가보기 시작한 것보다 Douglas Crockford: Advanced JavaScriptJavaScript에서 생성자 또는 객체 상속

비디오의 시작 부분에서, 그는 상속의 2 가지 유형에 대해 언급했다. 나는 내가 알고 있다고 생각하는 모든 것을 실현하지 못했다. 알지 못해. 그래서 Chrome 자바 스크립트 콘솔로 게임을 시작했고 상속 모델을 사용하여 무언가를 시도했습니다. 내가 Object.create를 사용하여 같은 일을 해봤보다

//create constructor 
function MyParent(){ 
    this.name = "joe"; 
    this.sayHi = function(){ 
     console.log(this.name); 
    } 
} 

//create child object and inherit from parent 
var myChild1 = new MyParent(); 
myChild1.name 
"joe" 
myChild1.sayHi() 
joe 

//add method to MyParent, so it can be accessed from myChild1 
MyParent.prototype.sayBye = function(){ console.log("bye");} 

myChild1.sayBye() 
bye 

//create another constructor 
function MyParent2(){ 
    this.sayHi = function(){ 
     console.log("hi"); 
    } 
} 

//make it inherit from MyParent, overwriting sayHi if object is instance of MyParent2 
MyParent2.prototype = new MyParent(); 

//overwrote sayHi 
var myChild11 = new MyParent2(); 
myChild11.sayHi(); 
hi 

//still same as MyParent as its not overwriten in MyParent2 
myChild11.name 
"joe" 

:

//create an object 
var myParent = { 
    name : "joe", 
    sayHi : function(){ 
     console.log(this.name) 
    } 
}; 

//it works 
myParent.sayHi() 
joe 

//create child object 
var myChild = Object.create(myParent); 
myChild.sayHi() 
joe 

//add bye method to myChild 
myChild.sayBye = function(){ console.log("bye"); } 
myChild.sayBye(); 
bye 

//add bye method to myParent - does not overwrite child's bye 
myParent.sayBye = function(){ console.log("bye2"); } 

//however adding sayBye2 to parent, becomes available on already created child 
myParent.sayBye2 = function(){ console.log("bye2"); } 
myChild.sayBye2(); 
bye2 
//but its the parent property 
myChild.hasOwnProperty("sayBye2") 
false 

//could make million objects inherit from each other vertically or horizontally 
var myChild2 = Object.create(myChild); 
myChild2.name 
"joe" 

지금까지 단지 첫 인상에 의해, 나는 어쩌면 내가 약간 후자를 선호, 두 모델 모두 좋아한다. 그것은 더 표현력 있고 강력한 것으로 보인다.

vs. 주제에 대한 검색을 수행했지만 각 접근법의 장단점을 설명하는 좋은 기사를 찾을 수 없습니다 (후자는 최신 브라우저에서만 지원되지만 간단한 해결 방법이 있습니다).). 내가 발견 한 게시물의 나머지 부분은 단지 tl : dr; 다소 지루하다.

제 질문은 어떤 유형의 상속이 필요합니까? 그와 관련된 특전이 있습니까? 둘 중 하나에 대한 주요 죄수? 둘 다 혼합 할 수 있니?)

감사

EDIT (. 예를 들어, 당신이 new Constructor()에 인수로 개체를 전달할 수있어) : 브라우저를 지원하지 않는 경우 Object.create() 대안을 만들기 위해 트릭을 보면 , 나는 어떻게 간단한 실현 해킹입니다. 기본적으로 빈 생성자를 만들고 부모 객체를 프로토 타입으로 할당하고 생성 된 생성자를 새 객체로 반환합니다. 이 얼마나 청초한 해킹!

if(typeof Object.create !== "function") { Object.create = function (o) { function F() {}; F.prototype = o; return new F(); }; } 

하지만 그 의미는 무엇입니까? 알고 있어야 할 일은?

답변

3

두 방법 모두 동등하게 강력한입니다. 어떤 사람들은 순수한 원형 접근법을 수용하지 않는다면 실제 JavaScript 마스터가 아니라고 말하지만 실제로는 모든 것이 여전히 프로토 타입 상속 인이며 이는 스타일 문제입니다.

필자는 고전적인 접근법을 사용하고 new 키워드와 함께 constructor 기능을 사용하는 것을 선호합니다.

왜?

  • 클래식 모델은 매우 잘 알려져 있습니다.
  • 내 개체에 init 함수를 구현할 필요가 없습니다. constructor이 이미 수행 한 것입니다. 여러분이 이미 알고 있듯이, 순수 원형 접근법은 constructor없이 당신을 떠날 것입니다. 그래서 새로 생성 된 객체를위한 초기화 로직을 실행해야한다면 초기화 함수 (일반적으로 init)를 구현해야합니다.

그러나, 나는 순수 프로토 타입 접근 방식은 조금 덜 장황하고 고전적인 상속을 구현하는 언어에 강한 배경없이 프로그래머가 쉽게 이해할 수 있습니다 것을 찾을 수 있습니다. 그런데

, 당신은 클래식 모델을 피해야 한 가지 불필요한 부모 constructor 로직을 실행하기 때문에 위하고있는 것처럼 new 키워드를 사용하여 상속이며 잠재적으로 바람직하지 않은 부작용이있을 수 있습니다. 이 맛의 모든 문제입니다, 마지막에

function A(val) { this.val = val; } 
A.prototype.alertVal = function() { alert(this.val); }; 

function B(val) { 
    A.call(this, val); //call parent constructor 
} 

B.prototype = Object.create(A.prototype); //inherit from A 
var b = new B('test'); 
b.alertVal(); //test 

을 나는 두 가지을 존중 :

아래처럼 Object.create를 사용한다. 어쩌면 다른 사람이 몇 가지 실질적인 장점/단점을 가지고이 답변을 향상시키고 싶지만 어떤 것도 찾을 수 없습니다.

+0

A.apply 방법은 어떻게 작동합니까? 이 경우 정확하게 무엇을합니까? –

+0

A가 생성자를 호출하고 A (B의 범위)와 A의 인수 (다시 B)를 전달합니까? –

+0

@JanNetherdrake 무언가를 쓰고 있었지만 그것을 얻었습니다. 컨텍스트 객체 (this가 가리키는 객체)를 설정하여 새로 생성 된 B 인스턴스에 'A'생성자 논리가 적용되도록합니다. . 만약 당신이'A();'를 호출했다면, 컨텍스트 객체는'window' 였을 것이고 그것은 당신이 원하는 것이 아닙니다. 자,'apply'와'call'의 차이점에 대해 읽어 보시기 바랍니다;) 부모의 생성자를 호출하는 것이 좀 더 의미가 있도록 예제를 업데이트했습니다. – plalx

0

new을 사용하여 개체를 구성하면 사용하는 것을 잊어 버리고 this에 추가하는 모든 속성이 전역 개체에 추가됩니다. 이런 이유로 나는 두 번째 접근법을 찾고있다.

내가 배운 또 다른 한 가지는 JavaScript에 "클래식"OOD를 적용하지 말아야한다는 것입니다. 그것은 이해되어야하는 자체 방식을 가지고 있으며, 실제로는 아주 좋습니다. 자바 스크립트에서 객체 프로그래밍 문제의 대부분은 "클래스"라는 개념을 자바 스크립트에 적용하려는 시도에서 비롯된 것이라고 생각합니다.

+0

예, Crockford는 생성자 이름이 대문자로 시작하는 이유는 우리에게 '새로운'사용을 상기시켜야한다는 것입니다. 나는 다른 것을 열어서, 이것이 내가 JS를 즐기고있는 이유입니다. 그래서 나는 JS에서 자바처럼 생각하지 않을 것이다. –