Gibt es eine Möglichkeit, diese Überschreibungsmethode von meiner Implantation aus aufzurufen, wenn ich die clone()
Methode von a Backbone.Model
überschreibe? Etwas wie das:
var MyModel = Backbone.Model.extend({
clone: function(){
super.clone();//calling the original clone method
}
})
javascript
inheritance
backbone.js
Andreas Köberle
quelle
quelle
Sie können auch die
__super__
Eigenschaft verwenden, die auf den Prototyp der übergeordneten Klasse verweist:var MyModel = Backbone.Model.extend({ clone: function(){ MyModel.__super__.clone.call(this); } });
quelle
__super__
ist ein Verweis auf den Prototyp des übergeordneten Elements, den das Backbone-Framework jedes Mal erstellt, wenn ein Backbone-Modell, eine Sammlung, ein Router oder eine Ansicht erweitert wird. Obwohl es sich nicht um eine Standardeigenschaft handelt, funktioniert es seit der Generierung des Frameworks browserübergreifend. Selbst die offiziellen Backbone-Dokumente erwähnen dies jedoch nicht und sagen, dass sie dieBackbone.Model.prototype.set.call(this, attributes, options);
Methode verwenden sollen. Beide scheinen jedoch gut zu funktionieren..set.
er.clone.
für den Anwendungsfall des OP sein?Backbone.Model.prototype.clone.call(this, attributes, options);
in seinem Fall.this.constructor
ist nicht garantiertMyModel
und würde einen Stapelüberlauf verursachen, wennMyModel
er als übergeordnete Klasse verwendet würde.Josh Nielsen hat dafür eine elegante Lösung gefunden , die einen Großteil der Hässlichkeit verbirgt.
Fügen Sie einfach diesen Ausschnitt zu Ihrer App hinzu, um das Backbone-Modell zu erweitern:
Backbone.Model.prototype._super = function(funcName){ return this.constructor.prototype[funcName].apply(this, _.rest(arguments)); }
Dann benutze es so:
Model = Backbone.model.extend({ set: function(arg){ // your code here // call the super class function this._super('set', arg); } });
quelle
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) { // Find the scope of the caller. 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 = {}; // Hack "super" functionality into backbone. Backbone.View.prototype._superFn = Backbone.Model.prototype._superFn = function(funcName, _caller) { var caller = _caller == null ? arguments.callee.caller : _caller; // Find the scope of the 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({ // className: "A", go1: function() { console.log("A1"); }, go2: function() { console.log("A2"); }, }); var B = A.extend({ // className: "B", go2: function() { this._super("go2"); console.log("B2"); }, }); var C = B.extend({ // className: "C", 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:
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.)quelle
Wenn Sie nur this._super () aufrufen möchten; ohne den Funktionsnamen als Argument zu übergeben
Backbone.Controller.prototype._super = function(){ var fn = Backbone.Controller.prototype._super.caller, funcName; $.each(this, function (propName, prop) { if (prop == fn) { funcName = propName; } }); return this.constructor.__super__[funcName].apply(this, _.rest(arguments)); }
Verwenden Sie dieses Plugin besser: https://github.com/lukasolson/Backbone-Super
quelle
Ich glaube, Sie können die ursprüngliche Methode zwischenspeichern (obwohl nicht getestet):
var MyModel = Backbone.Model.extend({ origclone: Backbone.Model.clone, clone: function(){ origclone();//calling the original clone method } });
quelle
Backbone.Model.prototype.clone
und seinthis.origclone()
. Es ist gleichbedeutend mitBackbone.Model.prototype.clone.call(this)
.backbone._super.js, aus meinem Kern: https://gist.github.com/sarink/a3cf3f08c17691395edf
// Forked/modified from: https://gist.github.com/maxbrunsfeld/1542120 // This method gives you an easier way of calling super when you're using Backbone in plain javascript. // It lets you avoid writing the constructor's name multiple times. // You still have to specify the name of the method. // // So, instead of having to write: // // var Animal = Backbone.Model.extend({ // word: "", // say: function() { // return "I say " + this.word; // } // }); // var Cow = Animal.extend({ // word: "moo", // say: function() { // return Animal.prototype.say.apply(this, arguments) + "!!!" // } // }); // // // You get to write: // // var Animal = Backbone.Model.extend({ // word: "", // say: function() { // return "I say " + this.word; // } // }); // var Cow = Animal.extend({ // word: "moo", // say: function() { // return this._super("say", arguments) + "!!!" // } // }); (function(root, factory) { if (typeof define === "function" && define.amd) { define(["underscore", "backbone"], function(_, Backbone) { return factory(_, Backbone); }); } else if (typeof exports !== "undefined") { var _ = require("underscore"); var Backbone = require("backbone"); module.exports = factory(_, Backbone); } else { factory(root._, root.Backbone); } }(this, function(_, Backbone) { "use strict"; // Finds the next object up the prototype chain that has a different implementation of the method. var findSuper = function(methodName, childObject) { var object = childObject; while (object[methodName] === childObject[methodName]) { object = object.constructor.__super__; } return object; }; var _super = function(methodName) { // Keep track of how far up the prototype chain we have traversed, in order to handle nested calls to `_super`. this.__superCallObjects__ || (this.__superCallObjects__ = {}); var currentObject = this.__superCallObjects__[methodName] || this; var parentObject = findSuper(methodName, currentObject); this.__superCallObjects__[methodName] = parentObject; // If `methodName` is a function, call it with `this` as the context and `args` as the arguments, if it's an object, simply return it. var args = _.tail(arguments); var result = (_.isFunction(parentObject[methodName])) ? parentObject[methodName].apply(this, args) : parentObject[methodName]; delete this.__superCallObjects__[methodName]; return result; }; // Mix in to Backbone classes _.each(["Model", "Collection", "View", "Router"], function(klass) { Backbone[klass].prototype._super = _super; }); return Backbone; }));
quelle
Falls Sie nicht genau wissen, was die übergeordnete Klasse ist (Mehrfachvererbung oder Sie möchten eine Hilfsfunktion), können Sie Folgendes verwenden:
var ChildModel = ParentModel.extend({ initialize: function() { this.__proto__.constructor.__super__.initialize.apply(this, arguments); // Do child model initialization. } });
Mit Hilfsfunktion:
function parent(instance) { return instance.__proto__.constructor.__super__; }; var ChildModel = ParentModel.extend({ initialize: function() { parent(this).initialize.apply(this, arguments); // Do child model initialization. } });
quelle
Übergeben Sie die übergeordnete Klasse als Option während der Instanziierung:
BaseModel = Backbone.Model.extend({ initialize: function(attributes, options) { var self = this; this.myModel = new MyModel({parent: self}); } });
Dann können Sie in Ihrem MyModel übergeordnete Methoden wie diese aufrufen
this.options.parent.method (); Beachten Sie, dass dadurch ein Aufbewahrungszyklus für die beiden Objekte erstellt wird. Damit der Garbage Collector seine Arbeit erledigen kann, müssen Sie die Aufbewahrung eines der Objekte manuell zerstören, wenn Sie damit fertig sind. Wenn Ihre Anwendung ziemlich groß ist. Ich möchte Sie ermutigen, sich eingehender mit hierarchischen Einstellungen zu befassen, damit Ereignisse zum richtigen Objekt gelangen können.
quelle
var self = this
ist nicht notwendig , in diesem Fall , da es nicht in einer Callback - Funktion ist zu verlieren , den Kontext.2 Funktionen unten, eine erfordert die Übergabe des Funktionsnamens, die andere kann "herausfinden", von welcher Funktion wir die Super-Version wollen
Discover.Model = Backbone.Model.extend({ _super:function(func) { var proto = this.constructor.__super__; if (_.isUndefined(proto[func])) { throw "Invalid super method: " + func + " does not exist in prototype chain."; } return proto[func].apply(this, _.rest(arguments)); }, _superElegant:function() { t = arguments; var proto = this.constructor.__super__; var name; for (name in this) { if (this[name] === arguments.callee.caller) { console.log("FOUND IT " + name); break; } else { console.log("NOT IT " + name); } } if (_.isUndefined(proto[name])) { throw "Super method for: " + name + " does not exist."; } else { console.log("Super method for: " + name + " does exist!"); } return proto[name].apply(this, arguments); }, });
quelle
So würde ich das machen:
ParentClassName.prototype.MethodToInvokeName.apply(this);
Für Ihr Beispiel lautet dies also:
Model.prototype.clone.apply(this)
quelle