2010-06-30 4 views
14

저는 javascript와 html5를 사용하여 간단한 플랫폼 게임을 작성하고 있습니다. OO 방식으로 자바 스크립트를 사용하고 있습니다. 상속 작업을 얻으려면 다음을 사용합니다.자바 상속 - instanceof 작동하지 않습니까?

// http://www.sitepoint.com/blogs/2006/01/17/javascript-inheritance/ 
function copyPrototype(descendant, parent) { 
    var sConstructor = parent.toString(); 
    var aMatch = sConstructor.match(/\s*function (.*)\(/); 
    if (aMatch != null) { descendant.prototype[aMatch[1]] = parent; } 
    for (var m in parent.prototype) { 
     descendant.prototype[m] = parent.prototype[m]; 
    } 
}; 

이 게시물을 위해 다음 예제를 고려하십시오. C는 C & B의 인스턴스 & A. 내가 잘못 때문에

function A() { 
this.Name = 'Class A' 
} 
A.prototype.PrintName = function() { 
alert(this.Name); 
} 

function B() { 
this.A(); 
} 
copyPrototype(B, A); 

function C() { 
this.B(); 
} 
copyPrototype(C, B); 

var instC = new C(); 

if (instC instanceof A) 
    alert ('horray!'); 

나는, 나는 horray 경고 상자가 표시 기대 알고있는 것처럼? 아니면 잘못된 방법으로 확인하고 있습니까? 또는 copyPrototype이 instanceof 연산자를 괴롭 히고 있습니까?

항상이 시간을내어 주셔서 감사합니다.

쇼.

답변

6

요즘에는 .prototype = new Thing()이 필요하지 않습니다. 나는 파티에 늦었지만 Object 만 사용할 수 있다고 생각합니다.부모 프로토 타입을 만들고 오버 라이딩 할 메소드를 재정의하십시오. 예 : 당신이 노드에서이 코드를 실행하면

var IDataSource = function(){ 
    throw new Error("Not implemented, interface only"); 
}; 

IDataSource.prototype.getData = function(){ 
    throw new Error("Not implemented."); 
}; 

var BasicDataSource = function(){}; 
BasicDataSource.prototype = Object.create(IDataSource.prototype); 
BasicDataSource.prototype.getData = function(){ 
    //[do some stuff, get some real data, return it] 
    return "bds data"; 
}; 

var MockDataSource = function(){}; 
MockDataSource.prototype = Object.create(IDataSource.prototype); 
MockDataSource.prototype.getData = function(){ 
    //[DONT DO some stuff return mock json] 
    return "mds data"; 
}; 

MockDataSource.prototype.getDataTwo = function(){ 
    //[DONT DO some stuff return mock json] 
    return "mds data2"; 
}; 


var MockDataSource2 = function(){}; 
MockDataSource2.prototype = Object.create(MockDataSource.prototype); 




var bds = new BasicDataSource(); 
console.log("bds is NOT MockDataSource:", bds instanceof MockDataSource); 
console.log("bds is BasicDataSource:", bds instanceof BasicDataSource); 
console.log("bds is an IDataSource:", bds instanceof IDataSource); 
console.log("bds Data:", bds.getData()); 


var mds = new MockDataSource(); 
console.log("mds is MockDataSource:", mds instanceof MockDataSource); 
console.log("mds is NOT a BasicDataSource:", mds instanceof BasicDataSource); 
console.log("mds is an IDataSource:", mds instanceof IDataSource); 
console.log("mds Data:", mds.getData()); 
console.log("mds Data2:",mds.getDataTwo()); 


var mds2 = new MockDataSource2(); 
console.log("mds2 is MockDataSource2:", mds2 instanceof MockDataSource2); 
console.log("mds2 is MockDataSource:", mds2 instanceof MockDataSource); 
console.log("mds2 is NOT a BasicDataSource:", mds2 instanceof BasicDataSource); 
console.log("mds2 is an IDataSource:", mds2 instanceof IDataSource); 
console.log("mds2 Data:", mds2.getData()); 
console.log("mds2 Data2:",mds2.getDataTwo()); 

당신은 얻을 것이다 :

bds is NOT MockDataSource: false 
bds is BasicDataSource: true 
bds is an IDataSource: true 
bds Data: bds data 
mds is MockDataSource: true 
mds is NOT a BasicDataSource: false 
mds is an IDataSource: true 
mds Data: mds data 
mds Data2: mds data2 
mds2 is MockDataSource2: true 
mds2 is MockDataSource: true 
mds2 is NOT a BasicDataSource: false 
mds2 is an IDataSource: true 
mds2 Data: mds data 
mds2 Data2: mds data2 

걱정을 생성자 또는 그러한 막무가내의 매개 변수에 대해.

+0

안녕하세요 j03m, 당신 말이 맞아요. 지금은 멋진 해결책이 될거예요.하지만이 질문은 꽤 오래되었습니다. , 그리고 그 당시에는 object.create에 대한 광범위한 지원이 없었습니다. 이것은 ECMA 스크립트 5 – Shawson

+0

ah note의 새로운 기능 이었기 때문에 타임 스탬프를 읽었습니다. – j03m

+0

참조 용으로 최신 답변을 갖고있는 것이 좋습니다. :) – Shawson

16

문제는 또 하나의 기능은 copyPrototype에 복사 생성자 프로토 타입의 속성 것으로, 예를 들면, 마지막에 C.prototype의 intenal [[Prototype]] 링크 단순히 Object.prototype 가리키는 것이다.

instC와 생성자의 프로토 타입의 프로토 타입 체인은 다음과 같이 : 당신이 볼 수있는

 
       [[Prototype]] 
    A.prototype -------------->|-------------------| 
           |     | 
    B.prototype -------------->| Object.prototype | ---> null 
           |     | 
    C.prototype -------------->|-------------------| 
     ^
     | 
     instC 

instanceof 연산자, 당신의 instC 객체를 프로토 타입 체인을 통과, 프로토 타입 체인에 미칠에만 C.prototypeObject.prototype .

당신은 예를 들어, 그들의 "부모"생성자의 개체 인스턴스로 생성자의 프로토 타입을 설정하여 원하는 것을 얻을 수 있습니다

function A() { 
    this.Name = 'Class A' 
} 

A.prototype.PrintName = function() { 
    alert(this.Name); 
} 

function B() { 
    //.. 
} 
B.prototype = new A(); 
B.prototype.constructor = B; // fix constructor property 


function C() { 
    //.. 
} 

C.prototype = new B(); 
C.prototype.constructor = C; // fix constructor property 

var instC = new C(); 
if (instC instanceof A) 
    alert('horray!'); 

이제 instC 객체의 프로토 타입 체인은 다음과 같습니다

 
      ---------------  ---------------  --------------- 
instC --> | C.prototype | -----> | B.prototype | -----> | A.prototype | 
      ---------------  ---------------  --------------- 
                   | 
                   V 
                 -------------------- 
                 | Object.prototype | 
                 -------------------- 
                   | 
                   V 
                   null 

권장 기사 :

+0

상속 형식이 무척 쉽게 이해할 수 있습니다. Crockford의 [begetObject()'] (http://javascript.crockford.com/prototypal.html) 기법 이상의 것입니다. 당신의 방법에 대한 단점이나'begetObject()'에 대한 이점이 있습니까? '이'여전히 당신이 기대하는 것입니까? 그리고이 기법을 직접 사용합니까? – Andrew

+0

네, 좋은 해결책입니다. 나는 자바 스크립트에서 많은 다른 접근법을 읽었습니다. 나는 이걸 줄거야! 건배. – Shawson

+0

hmm- 내 예제에서 실제로 지적 했어야 할이 메서드의 문제는 모든 생성자가 실제로 체인을 통해 다시 전달해야하는 매개 변수 (위치)를 받아 들인다는 것입니다. 어떻게이 방법을 사용하여 가능한 모든 아이디어? – Shawson

1

나는 instanceof 함수를 작동시키는 솔루션을 발견했으며, 상속 체인을 통해 생성자 매개 변수를 전달할 수있게되었습니다. 해결책은 여기에 자세히 설명되어 있습니다. https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Details_of_the_Object_Model - 내 클래스 구조는 이제 다음과 같이 보입니다.

function A(p) { 
this.Position = p || new Vector2d(0,0); 
} 

function B(p) { 
this.base = A; 
this.base(p); 
} 
B.prototype = new A; 

function C(p) { 
this.base = B; 
this.base(p); 
} 
C.prototype = new B; 

if(C instanceof A) 
    alert (' it worked!! '); // you now see this alert box! 

왜이 기능이 작동하지 않았던 지에 대한 감사의 CMS!

http://8weekgame.shawson.co.uk/에있는 전체 프로젝트 (글을 쓰면서이 새로운 OO 방법을 아직 보지 못한 오래된 빌드)를 확인할 수 있습니다. 최신 게시물을 확인하십시오.

+0

안녕하세요 @ shawson, 각 생성자에'this.base'를 대입하는 대신에 그 속성이 유용하지 않으면 다른 생성자를 직접 호출하여 올바른'this' 값을 설정하고'p' 인수를 전달할 수 있습니다 , 당신은''call'' (https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Function/call) 메쏘드를 사용하여 그것을 할 수 있습니다, 예를 들어,'B' :'A.call (this, p); ' – CMS

+0

이것은 나를 위해, 예를 들어 작동하지 않습니다 이 코드를 실행할 때 경고가 표시되지 않습니다. –

+0

흥미롭게도, 나는 이것을 크롬에 콘솔에 붙여 넣었고 나에게도 그다지 문제가되지 않았다. 어쨌든 지금 resig 방법을 사용하겠습니다. http://ejohn.org/blog/simple-javascript-inheritance/ – Shawson

관련 문제