2013-05-03 5 views
0

추가 된 상속을 사용하여 모듈 패턴을 파악하려고합니다. 저는 대학 배경에서 왔는데, 주로 트렁크에 자바가 있습니다. 그러나 저는 약 10 년 동안 웹 기술을 사용해 왔습니다. 나는 자바 스크립트로 약 1 년 ..."OOP"JavaScript 파악 : 상속을 사용하는 모듈 패턴

어쨌든, 나는 간단한 상속 (.prototype) 예제를 시도하고있다. People 개체에서 Gentleman을 추가 한 다음 .toString() 메서드를 사용하여 나열 할 수 있습니다. GentlemanHuman에 속하는 아이입니다. "추상적 인"Human을 구현하기 전까지는 좋았지 만 코드는 실행되지 않습니다.

내 코드와 관련하여 잘못된 점에 대해 의견을 보내주십시오. 모듈/프로토 타입 접근법을 유지하고 싶습니다만, 내가 잘못하고있는 것은 무엇입니까? 또한 this은 다른 상황에서 어떤 의미인지 들어 보았습니다. 즉, People에있는 개인 _people을 직접 사용할 수는 있지만 서브 모듈에서는 this._name을 사용해야합니까?

var People = People || {}; 

People = (function() { 
    var People = function(){ 
     this._people = []; 
    }; 

    var addGentleman = function (name) { 
     this._people.push(new People.Gentleman(name)); 
    }; 

    var getList = function() { 
     var temp = []; 

     for (var i = 0; i < this._people.length; i++) { 
      temp.push(this._people[i].toString()); 
     } 

     return temp; 
    }; 

    People.prototype.constructor = People; 
    People.prototype.addGentleman = addGentleman; 
    People.prototype.getList = getList; 

    return People; 
})(); 

People.Human = (function() { 
    var Human = function (name, hasLadyParts) { 
     this._name = name; 
     this._hasLadyParts = hasLadyParts; 
    }; 

    var hasLadyParts = function() { 
     return this._hasLadyParts; 
    }; 

    var toString = function() { 
     var str = this._name; 
     if (!this._hasLadyParts) str += ' no'; 
     return str + ' lady parts.'; 
    }; 

    Human.prototype.constructor = Human; 
    Human.prototype.hasLadyParts = hasLadyParts; 
    Human.prototype.toString = toString; 

    return Human; 
})(); 

People.Gentleman = (function() { 
    var Gentleman = function (name) { 
     People.Human.call(this, name, false); 
    } 

    var toString = function() { 
     return 'Mr.' + People.Human.toString(); 
    }; 

    // Gentleman.prototype = Object.create(People.Human.prototype); 
    Gentleman.prototype.constructor = Gentleman; 
    Gentleman.prototype.toString = toString; 

    return Gentleman; 
})(); 

$(function() { 
    var people = new People(); 
    people.addGentleman('Viktor'); 
    people.addGentleman('Joakim'); 
    var list = people.getList(); 
    var $ul = $('#people'); 

    for (var i = 0; i < list.length; i++) { 
     $ul.append('<li>' + list[i] + '</li>'); 
    } 
}); 

바이올린 : 나는 코드를 업데이트하고 조금 바이올린했습니다 : http://jsfiddle.net/5CmMd/5/

편집. 이 기능을 작동 시키면 대부분의 디자인을 이해할 수 있다고 생각합니다. 이 예제는 JavaScript 토지를 방문하는 미래의 OOP 프로그래머를위한 간단한 튜토리얼로도 작용할 것이라고 나는 생각한다.

+0

패턴 설명에 대한 링크를 제공 할 수 있습니까? 나는 일하는 것을 원하지 않는 많은 일들을 볼 수 있지만, 이드는 일하는 패턴 측면에서 오히려 문구를 사용한다. –

+0

이 패턴은 실제로 잘 설명되지 않습니다. 나는 JS 토론에서 받아 들일 수있는 것으로 함께 나에게 맞는 것을 결합하려고 노력하고있다. 이 패턴에 대한 한 가지 매우 빠른 시도 : http://stackoverflow.com/questions/8683125/combining-inheritance-with-the-module-pattern 지옥, 원하는 것을 자유롭게 변경하고 대부분의 설명을 읽을 수 있습니다. 그들이 잘 정의되어 있다면. :) – Viktor

답변

1

주요 문제는 신사의 원형에 있다고 생각합니다. 기능 :

을 할당이 시도 :

var People = People || {}; 

People = (function() { 
    var _people = []; 

    var People = function(){}; 

    var addGentleman = function (name) { 
     _people.push(new People.Gentleman(name)); 
    }; 

    var getList = function() { 
     var temp = []; 

     for (var i = 0; i < _people.length; i++) { 
      temp.push(_people[i].toString()); 
     } 

     return temp; 
    }; 

    People.prototype = { 
     constructor: People, 
     addGentleman: addGentleman, 
     getList: getList 
    }; 

    return People; 
})(); 

People.Human = (function() { 
    this._name; 

    var Human = function (name) { 
     this._name = name; 
    }; 



    Human.prototype = { 
     constructor: Human, 
    }; 

    return Human; 
})(); 

People.Gentleman = (function() { 

    var Gentleman = function (name) { 
     People.Human.call(this, name);  
    } 

    var toString = function() { 
     return 'Mr. ' + this._name; 
    }; 

    Gentleman.prototype = Object.create(People.Human.prototype); 


    Gentleman.prototype.constructor = Gentleman; 
    Gentleman.prototype.toString = toString; 

    return Gentleman; 
})(); 

$(function() { 
    var people = new People(); 
    people.addGentleman('Viktor'); // this is me 
    people.addGentleman('Joakim'); // and my friend! 
    var list = people.getList(); 
    var $ul = $('#people'); 

    for (var i = 0; i < list.length; i++) { 
     $ul.append('<li>' + list[i] + '</li>'); 
    } 
}); 

당신은 내가 새로운를 추가 한 것을 볼 수 있습니다 하나를 위해 다른 위해 사용 = 대신하는,의 youve 인간로부터 상속 된 프로토 타입을 덮어 쓰는 toString 메소드를 프로토 타입 객체에 덮어 쓰지 않고 이미 존재하는 객체를 덮어 쓴다. 나는 패턴이 이것을하기에 더 좋은 방법을 가지고 있는지 모른다. (익숙하지 않다.) 당신은이 작업을 수행 할 수

그것은 더 적절한 것 같다 경우 :

Gentleman.prototype = Object.create(People.Human.prototype, 
{ 
    constructor : { configurable: true, get : function() { return Gentleman } }, 
    toString : { configurable: true, get : function() { return toString } } 
}); 
+0

아하, 그래서 나는'prototype ='표기법을 사용해야한다.'prototype = {}'이 아니라면 나는 그것을 덮어 쓰기 때문이다. – Viktor

+0

예 - 두 번째 할당을 할 때 이전 행에서 설정 한 객체 참조를 덮어 씁니다. zeroflags 링크를 읽으면 object.create()를 사용하여 추가 속성을 추가 할 수도 있습니다 - 예를 들어 잘못된 업데이트 –

+0

좋아요! 나는 또 다른'Human' 메쏘드로 내 모범을 업데이트했다. 그러나 이것은 추상적이 아니다. 내 바이올린을 업데이트하여 작동하도록 하시겠습니까? 나는 덮어 쓰기를 얻고 따라서 나는 첫 번째 해결책을 사용하고있다. – Viktor

2
Gentleman.prototype = Object.create(People.Human.prototype); 

Gentleman.prototype = { 
    constructor = Gentleman, 
    toString = toString 
}; 

constructor: Gentleman, ... 작아야합니다. 또한 prototype에 두 번 할당하고 덮어 씁니다. 그 결과 Gentleman은 더 이상 Human에서 상속받지 않습니다. 추가 할 내용 :

Gentleman.prototype.toString = toString; 

또는 Object.create() 호출로 속성을 추가하십시오. this에 관해서는 see reference

:이 변수이기 때문에

직접 _people를 사용할 수 있습니다. People의 모든 인스턴스는 같은 사람 목록을 공유합니다.

개체를 메서드로 호출 할 때 this은 개체 자체를 참조합니다. Human은 모두 자신의 이름을 가져야하므로 this._namethis ^^ human의 이름을 나타냅니다. 따라서 aGentleman.toString()은 정확히 this 신사의 이름을 반환합니다.

People.Human = (function() { 
    this._name; //<- does not do anything. 
+0

그러면 어떻게 생성자 (args) {슈퍼 (args); // 신사 코드}'? 그리고 어떻게 기본 "클래스"'사람들''이 '를 사용하지 않아도됩니까? – Viktor

+0

@Viktor 질문 1 : 이미 해보았습니다. 나는 그 질문을 이해하지 못한다. 질문 2 : Java를 알고 있으므로 필드와 변수의 차이점을 알 수 있습니다. 'this'를 사용하면 필드에 액세스 할 수 있습니다. '_people'은 변수입니다. – zeroflagL

+0

1. 그러나'Gentleman.prototype = Object.create (People.Human.prototype);을 삭제하면 여전히 작동하지 않습니다. 업데이트 된 바이올린을 제공하겠습니까? :) – Viktor