Dojoから来たので、 Dojoの機能が本当に恋しいです。私は複雑なアプリケーションを開発していて、ノードから生きている地獄をハッキングして、それをもっと...まあ、もっと強力にしました。declare()
lang.inherits()
これが実際に何をするかを示す例です:
var First = declare( null, {
one: function(p){
console.log("one in First");
console.log(p);
return 1000;
},
two: function(p){
console.log("two in First");
console.log(p);
return 1001;
},
constructor: function(a){
this.a = a;
console.log("Constructor of First called");
},
})
var Second = declare( First, {
two: function( p ){
console.log("two in Second");
console.log( p );
a = this.inherited(arguments);
console.log("Inherited function returned: " + a );
},
constructor: function(a){
console.log("Constructor of Second called, and this.a is...");
console.log( this.a );
},
})
console.log("Creating first...");
first = new First(10);
console.log("Creating second...");
second = new Second( 20 );
console.log( "first.a:")
console.log( first.a );
console.log( "second.a:")
console.log( second.a );
console.log( "first.one(1):")
first.one(1);
console.log( "first.two(2):")
first.two(2);
console.log( "second.one(3):")
second.one(3);
console.log( "second.two(4):")
second.two(4);
表示されます:
Creating first...
Constructor of First called
Creating second...
Constructor of First called
Constructor of Second called, and this.a is...
20
first.a:
10
second.a:
20
first.one(1):
one in First
1
first.two(2):
two in First
2
second.one(3):
one in First
3
second.two(4):
two in Second
4
two in First
4
Inherited function returned: 1001
この関数lang.inherits()
がミニマルである理由はわかっています。nodejsは、Javascriptで「クラス」、プロトタイプ、およびオブジェクトを処理する特定の方法を課したくないのです。
ただし、そこにある多くのコードは次のものでいっぱいです。
function SomeClass( options ){
this.options = options;
}
SomeClass.prototype.functionOne = function(something){
//...
}
SomeClass.prototype.functionTwo = function(something){
//...
}
どれが(そして...まあ、そうすべきですか?)次のように書くことができます:
SomeClass = declare( null, {
constructor: function(options){
this.options = options;
},
functionOne: function(something){
// ...
},
functionTwo: function(something){
// ...
},
})
できるという利点があります:
SomeOtherClass = declare( SomeClass, {
constructor: function(){
this.options['manipulate'] ++;
},
functionOne: function(something){
this.inherited(arguments); // Call the superclass method
// ...
},
})
これにより、親などのコンストラクターが自動的に呼び出されます(実装するためthis.inherited()
に、実際には関数のハッシュマップを作成することになりました。これは、事実上名前がないためです)。
これとDojoの主な違いは、このバージョンは多重継承とミックスインを実装していないことです。ただし、クライアント側の環境では多重継承/ミックスインは理にかなっていますが、サーバー側のプログラムではそれらが大きなやり過ぎになると思います。OK...これがコードです。このコードで本当に間違っていることを見つけることができますか?
私はすでに存在する何かを発明しましたか?
どうぞ...
var
dummy
;
var declare = exports.declare = function(superCtor, protoMixin) {
// Kidnap the `constructor` element from protoMixin, as this
// it mustn't get copied over into the prototype
var constructor = protoMixin.constructor;
delete protoMixin.constructor;
// The function that will work as the effective constructor. This
// will be returned
var ctor = function(){
// Call the superclass constructor automatically
if( typeof( superCtor.prototype.constructor === 'function' ) ){
superCtor.prototype.constructor.apply( this, arguments );
}
// Call its own constuctor (kidnapped a second ago)
if( typeof( constructor ) === 'function' ){
constructor.apply( this, arguments );
}
};
// The superclass can be either an empty one, or the one passed
// as a parameter
superCtor = superCtor === null ? function(){} : superCtor;
// Create the new class' prototype. It's a new object, which happen to
// have its own prototype (__proto__) set as the superclass' and the
// `constructor` attribute set as ctor (the one we are about to return)
ctor.super_ = superCtor;
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
// Implement inherited() so that classes can run this.inherited(arguments)
// This will only work for sub-classes created using declare() as they are
// the ones with the _inheritMap in their prototype
protoMixin.inherited = function(args){
var name, fn;
// Look for the name in the _inheritMap
name = this._inheritMap[ args.callee ];
if( name ){
fn = superCtor.prototype[name];
if( fn ){
return fn.apply( this, args );
} else {
throw( new Error("Method " + name + "() not inherited!") );
}
}
}
// Copy every element in protoMixin into the prototype.
ctor.prototype._inheritMap = {}
for( var k in protoMixin ){
ctor.prototype[ k ] = protoMixin[ k ];
ctor.prototype._inheritMap[ protoMixin[ k ] ] = k;
}
return ctor;
};
exports = module.exports = declare;