Ausgehend von den Antworten von geek_dave und charlysisto habe ich dies geschrieben, um this._super(funcName, ...)
Unterstützung für Klassen mit mehreren Vererbungsebenen hinzuzufügen . In meinem Code hat es gut funktioniert.
Backbone.View.prototype._super = Backbone.Model.prototype._super = function(funcName) {
var scope = null;
var scan = this.__proto__;
search: while (scope == null && scan != null) {
var names = Object.getOwnPropertyNames(scan);
for (var i = 0; i < names.length; i++) {
if (scan[names[i]] === arguments.callee.caller) {
scope = scan;
break search;
}
}
scan = scan.constructor.__super__;
}
return scan.constructor.__super__[funcName].apply(this, _.rest(arguments));
};
Ein Jahr später habe ich einige Fehler behoben und die Dinge schneller gemacht. Unten ist der Code, den ich jetzt benutze.
var superCache = {};
Backbone.View.prototype._superFn = Backbone.Model.prototype._superFn = function(funcName, _caller) {
var caller = _caller == null ? arguments.callee.caller : _caller;
var scope = null;
var scan = this.__proto__;
var className = scan.constructor.className;
if (className != null) {
var result = superCache[className + ":" + funcName];
if (result != null) {
for (var i = 0; i < result.length; i++) {
if (result[i].caller === caller) {
return result[i].fn;
}
}
}
}
search: while (scope == null && scan != null) {
var names = Object.getOwnPropertyNames(scan);
for (var i = 0; i < names.length; i++) {
if (scan[names[i]] === caller) {
scope = scan;
break search;
}
}
scan = scan.constructor.__super__;
}
var result = scan.constructor.__super__[funcName];
if (className != null) {
var entry = superCache[className + ":" + funcName];
if (entry == null) {
entry = [];
superCache[className + ":" + funcName] = entry;
}
entry.push({
caller: caller,
fn: result
});
}
return result;
};
Backbone.View.prototype._super = Backbone.Model.prototype._super = function(funcName) {
var args = new Array(arguments.length - 1);
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i + 1];
}
return this._superFn(funcName, arguments.callee.caller).apply(this, args);
};
Dann geben Sie diesen Code:
var A = Backbone.Model.extend({
go1: function() { console.log("A1"); },
go2: function() { console.log("A2"); },
});
var B = A.extend({
go2: function() { this._super("go2"); console.log("B2"); },
});
var C = B.extend({
go1: function() { this._super("go1"); console.log("C1"); },
go2: function() { this._super("go2"); console.log("C2"); }
});
var c = new C();
c.go1();
c.go2();
Die Ausgabe in der Konsole lautet wie folgt:
A1
C1
A2
B2
C2
Interessant ist, dass die Klasse C this._super("go1")
die Klassenhierarchie scannt, bis sie in Klasse A getroffen wird. Andere Lösungen tun dies nicht.
PS Kommentieren Sie die className
Einträge der Klassendefinitionen aus, um das Zwischenspeichern der _super
Suche zu ermöglichen . (Es wird davon ausgegangen, dass diese Klassennamen in der Anwendung eindeutig sind.)