2011-01-24 4 views
2

이 코드의 문제점은 무엇입니까? 누군가가 JavaScript Object Inheritance를 도와 줄 수 있습니까? 나는 바보처럼 느껴지기 시작했다 !! 사전에JavaScript Object Inheritance - 내가 뭘 잘못하고 있니?

감사합니다, 샘

function Human(name, sex) { 
    this.name = name; 
    this.sex = sex; 
}; 

function Man(name) { 
    Man.prototype = new Human(name, "Male"); 
}; 

var m = new Man("Sam Striano"); 
alert(m.name); //<-- = Undefined 

답변

1

자바 스크립트 고전 상속을 모방하기 위해 일반적으로 두 단계에있다 :

  1. 귀하의 하위 클래스 생성자는 부모 생성자를 호출해야

    귀하의 서브 클래스의 프로토 타입이 상위 프로토 타입

에 체인 필요
  • 첫 번째 단계는 일반적으로 다음과 같습니다.

    function Subclass(blah) { 
        ParentClass.apply(this, arguments); 
    } 
    

    두 번째 단계는 더 까다 롭습니다. 당신이 당신의 스크립트 (A Node.js를 환경에서처럼) 실행 위치를 정확히 알고하지 않는 한 __proto__ 속성을 구현 JS 환경에서 당신이

    Subclass.prototype = { 
        __proto__ : ParentClass.prototype, 
        subclassMethod1: function() { /* ... */ } 
    } 
    

    을 할 수있는, 당신은 당신의 스크립트에 사용할 수있는 __proto__에 의존 할 수 없다 그래서 일반적인 접근 방식은 Crockford's object() method를 사용하는 것이 필요합니다 : 그것의 요점이다

    if (typeof Object.create !== 'function') { 
        Object.create = function (o) { 
         function F() {} 
         F.prototype = o; 
         return new F(); 
        }; 
    } 
    Subclass.prototype = Object.create(ParentClass.prototype); 
    Subclass.prototype.subclassMethod1 = function() { /* ... */ } 
    

    합니다. ES5 런타임에는 Object.create()이 이미 내장되어있을 수 있습니다.

    부모 클래스의 재정의 된 메소드를 쉽게 호출 할 수있는 능력과 같은 고전적인 상속을 완료하려면 남은 사항이 있습니다. 지금 가지고있는 것을 가지고 Subclass 메소드에 ParentClass.prototype.overridenMethod.call(this, arg1, arg2)과 같은 것이 필요할 것입니다. 일부 OO 라이브러리는 서브 클래스 인스턴스 각각에 추가 cruft를 유용하게 정의하므로 this.superclass.overridenMethod(arg1, arg2)과 같은 것을 사용할 수 있습니다.

    그 cruft에의 구현은 독자에게 연습 문제로 남겨은)

  • +0

    메소드는 서브와 서브에서 정의되어야합니까? 자바 스크립트를 사용하여 고전적인 상속의 완전한 예제를 보여줄 수 있습니까? – Sam

    2

    이 대신 원하는 :

    function Man(name) { 
        Human.call(this, name, "Male"); 
    } 
    

    그 코드는 단지 전화를하려는 것 같다

    무엇을 부모의 생성자 Human은 프로토 타입 상속입니다. 위 코드는 Human의 생성자를 가져와 this - 새 Man 개체에 적용합니다.

    코드를 선 Man.prototype = new Human(name, "Male")Man의 프로토 타입 새로운 남자가을 만들 때마다 변화

    무엇. 뿐만 아니라 프로토 타입 객체를 다시 할당하기 때문에 완성 된 객체는 이후 할당 된 객체에만 적용됩니다. 즉, 첫 번째 객체가 아닙니다. 따라서 m.name은 정의되지 않습니다. 위의 내 코드에서와 같이 부모의 생성자를 호출하는 것이

    적절한 프로토 타입 상속

    참고 하지 원인 Man 자동 Human.prototype에 할당 된 방법을 상속하는 것입니다. 이 작업을 수행하는 가장 좋은 방법은 Human.prototypeMan.prototype에 복제하지만 모든 생성자 외부에 복제하는 것입니다. 이처럼 :

    function Man(name) { 
        Human.call(this, name, "Male"); 
    } 
    
    function inherit(parent, child) { 
        if (Object.create) child.prototype = Object.create(parent.prototype); 
        else { 
         for (var key in parent.prototype) { 
          if (!parent.prototype.hasOwnProperty(key)) continue; 
          child.prototype[key] = parent.prototype[key]; 
         } 
        } 
    } 
    
    inherit(Human, Man); 
    

    이 오히려 자세한 보일 수 있으며, 대안이 할 수 있습니다 :

    Man.prototype = new Human('no name', 'Male'); 
    

    어떤 을 작동하지만, 우리가 강제하고 있기 때문에 원치 않는 부작용이 발생 더플 이름을 prototype에 할당하면 Human에 대한 생성자가 프로토 타입을 할당하기위한 추가 시간을 호출하게됩니다. 이 경로를 따라 가면 나중에 에 속성을 할당하는 것 이상의 작업을 수행하기 위해 Human 생성자를 변경해야합니다.

    +0

    프로토 타입과 "__prototype__"의 차이점은 무엇입니까? – Sam

    +0

    문자열, 배열, 숫자, 부울 등과 비슷합니까? 그래서 당신이주는이 예제는 "Prototypical Inheritance"가 아닙니다. – Sam

    +0

    @Sam, 제 실수는'__proto__'를 의미한다고 생각합니다. 새 객체를 생성 한 함수의 프로토 타입에 새 객체를 연결하는 것입니다. 사용해서는 안되며 자세한 내용은 https : //developer.mozilla를 참조하십시오.org/ko/JavaScript/Reference/Global_Objects/Object/proto –

    1

    나는 당신이 Human에서 상속 속성에서 Man 클래스를 가지고있다 계신 생각합니다. 올바른 방향으로 가고 있지만 Man의 원형 객체로 새로운 Human 인스턴스를 한 번 적용해야합니다.

    function Human(name, sex) { 
        this.name = "some default"; 
        this.sex = sex; 
    }; 
    
    function Man(name) { 
        if(name !== undefined) 
         this.name = name; 
    }; 
    Man.prototype = new Human(name, "Male"); 
    Man.prototype.constructor = Man; 
    
    var m = new Man("Sam Striano"); 
    
    alert(m.name); // alerts "Sam Striano" 
    alert(m.sex); // alerts "Male" 
    
    +0

    이제 나는 이것과 "Box9"에서 위의 대답 사이에 혼란 스럽습니까 ??? – Sam

    +0

    @ 샘 : 어떤 부분을 혼동하고 있습니까? – user113716

    +0

    @Sam : [구현 방법에 대한 예가 있습니다.] (http://jsfiddle.net/Xyg3s/). '인간 '에 프로토 타입을 넣은 몇 가지 항목이 있는데, 모든 인간에게 적용될 것입니다. 그러면 각각의 Human 인스턴스는'Man'과'Woman'에 대한 부모 클래스로서의 역할을하는'sex' 속성을 가질 수 있습니다. 그러면 각각의'Man'은 자신의'name' 속성을 가질 수 있습니다. 'Human'은'name'을 경고하는'speak' 함수를 가지고 있기 때문에'Man'은 각각 자신의'name'을 말할 수 있습니다. – user113716

    1

    는 지금까지 내가 아는 한, 당신은 prototypeconstructor 모든 물건을 처리해야하고, inerithance이 방법으로 관리 할 수있다 :이 도움이

    
    // Define superclass  
    function Human(name, sex) { 
        this.name = name; 
        this.sex = sex; 
    }         
    
    // Define superclass methods  
    Human.prototype.method1 = function() { 
        alert('This is the call to ORIGINAL method1() with name: ' + this.name + ' and sex: ' + this.sex); 
    } 
    
    // Define subclass  
    function Man(name, age) {           
        this.constructor.apply(this, [ name, 'Man' ]); 
        this.age = age; 
    }  
    
    // Define subclass inerithance 
    Man.prototype = new Human(); 
    
    // Define subclass methods 
    Man.prototype.method1 = function() { 
        alert('This is the call to OVERWRITE method1() with name: ' + this.name + ' and sex: ' + this.sex + ' and age: ' + this.age); 
        this.constructor.prototype.method1.apply(this); 
    } 
    
    var m = new Man('Sam Satriano', 30); 
    m.method1(); 
    // Should alert: 
    // This is the call to OVERWRITE method1() with name: Sam Satriano and sex: Man and age: 30 
    // This is the call to ORIGINAL method1() with name: Sam Satriano and sex: Man 
    

    희망을. 차오!

    상속 싸움에 점점없이
    +0

    Btw에는 '슈퍼'동작을 시뮬레이트하는 몇 가지 흥미로운 jQuery 플러그인 (로우 프로 https://github.com/danwrong/low-pro-for-jquery/)이 있습니다. – lomanf

    +0

    Man 생성자에서 동일한 생성자가 아니라 부모 생성자를 호출하려고합니다. 당신의 예제는 상속을 설정할 때'Man.prototype = new Human()'다음에 프로토 타입에 생성자 프로퍼티를 수정하지 않았기 때문에 작동합니다 –

    1

    이 문제는 다음에 코드를 변경하여 해결할 수 있습니다

    function Human(name, sex) { 
        this.name = name; 
        this.sex = sex; 
    }; 
    
    function Man(name) { 
        // This is how you call the parent's constructor 
        Human.call(this, name, "Male"); 
    }; 
    
    // The call to setup the prototype only needs to happen once 
    // Not in every instantiation of the object 
    Man.prototype = new Human(); 
    // Have to fix the constructor, right now it's set to Human 
    Man.prototype.constructor = Man; 
    
    var m = new Man("Sam Striano"); 
    >> m.name // outputs "Sam Striano"; 
    >> m instanceof Human // outputs true 
    

    이 여전히 상속 할 수있는 이상적인 방법이 아닙니다. 나는 좋은 JS 상속을 만드는 것을 설명하는 것을 올렸다. http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html

    관련 문제