拡張されるオブジェクトで実行される拡張メソッドによって実装されるポリモーフィズムをサポートするマルチレベル継承を実装したいと思います(外部ユーティリティまたは関数によってではなく、拡張されるオブジェクトの観点から)。
tl;dr jsfiddle はこちら: http://jsfiddle.net/arzo/VLkF7/
私は何をしたいですか?
var MyObj = {name: 'object', toString: function() {return this.name;}};
MyObj.extend = function(objectToBeMerged) {
var objs=[this, objectToBeMerged],
newobj={},
obj;
for(var i in objs) {
for(var k in (obj=objs[i]) ) if (obj.hasOwnProperty(k)) newobj[k]=obj[k];
}
return newobj;
}
console.assert(MyObj.extend, 'ERROR: this should pass');
var ActionObj = MyObj.extend({name: 'action abstract object', exec: 'implemtation', undo: 'implementation of opposite action here'});
var DragNDrop = ActionObj.extend({name: 'drag&drop action', exec: function(){console.log('did d&d');}})
//unfortunately following assert will not get through, because MyObj.extend cannot iterate over ActionObj properties
if(DragNDrop.toString) console.info('MyObj.extend iterated over MyObj\'s properties')
console.assert(DragNDrop.undo, 'but MyObj.extend did not iterate over ActionObj properties, undo action is missing in this object:', DragNDrop)
;
上記のコードの問題は何ですか? これが通常の場合、たとえば C++ 継承の場合、 DragNDrop にはundoメソッドがありますが、そうではありません。が実行されます(したがって、 ActionObj.extend を実行する場合、関数のキーワードthisがMyObjではなくActionObjに評価されるように拡張したいと思います)
この問題の解決策は、次のような jQuery.extend の _.extend を使用することです。
//add here code in previous quote in this post...
MyUtils = {}
MyUtils.extend = function(objectToBeMerged, parent) {
var objs=[parent || this, objectToBeMerged],
newobj={},
obj;
for(var i in objs) {
for(var k in (obj=objs[i]) ) if (obj.hasOwnProperty(k)) newobj[k]=obj[k];
}
return newobj;
}
console.assert(MyObj && ActionObj, 'are you sure you have added code from previous block?');
var DnDAction=MyUtils.extend({name: 'drag&drop action', exec: function(){console.log('did d&d');}},ActionObj);
if (DnDAction.undo) console.info('using MyUtils.extend works fine and .undo is defined as expected in', DnDAction)
;
ただし、上記の解決策には外部ツールを使用する必要があります。MyUtils
この場合、これは実際にはポリモーフィックな解決策ではありません。
MyObj.extend を強制的に実行時に評価された (when-defining-evaluated ではない)this
式で反復処理する方法を知っていますか?