백본에서 슈퍼
의 clone()
메서드를 재정의 할 때 Backbone.Model
이식에서이 재정의 된 메서드를 호출하는 방법이 있습니까? 이 같은:
var MyModel = Backbone.Model.extend({
clone: function(){
super.clone();//calling the original clone method
}
})
다음을 사용하고 싶을 것입니다.
Backbone.Model.prototype.clone.call(this);
(현재 모델) 의 컨텍스트 clone()
를 Backbone.Model
사용 하여 원래 메서드를 호출합니다 this
.
에서 백본 문서 :
super에 대한 간략한 설명 : JavaScript는 super를 호출하는 간단한 방법을 제공하지 않습니다. 동일한 이름의 함수는 프로토 타입 체인에서 더 높게 정의됩니다. set 또는 save와 같은 핵심 함수를 재정의하고 부모 개체의 구현을 호출하려면 명시 적으로 호출해야합니다.
var Note = Backbone.Model.extend({
set: function(attributes, options) {
Backbone.Model.prototype.set.apply(this, arguments);
...
}
});
__super__
부모 클래스 프로토 타입에 대한 참조 인 속성을 사용할 수도 있습니다 .
var MyModel = Backbone.Model.extend({
clone: function(){
MyModel.__super__.clone.call(this);
}
});
Josh Nielsen 은 많은 추함을 숨기는 우아한 해결책을 찾았습니다 .
이 스 니펫을 앱에 추가하여 Backbone의 모델을 확장하기 만하면됩니다.
Backbone.Model.prototype._super = function(funcName){
return this.constructor.prototype[funcName].apply(this, _.rest(arguments));
}
그런 다음 다음과 같이 사용하십시오.
Model = Backbone.model.extend({
set: function(arg){
// your code here
// call the super class function
this._super('set', arg);
}
});
geek_dave와 charlysisto가 제공 한 답변에서 작업하면서 this._super(funcName, ...)
여러 수준의 상속이있는 클래스 에 지원 을 추가 하기 위해 이것을 작성했습니다 . 내 코드에서 잘 작동합니다.
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));
};
1 년 후 몇 가지 버그를 수정하고 작업 속도를 높였습니다. 다음은 지금 사용하는 코드입니다.
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);
};
그런 다음 다음 코드가 제공됩니다.
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();
콘솔의 출력은 다음과 같습니다.
A1
C1
A2
B2
C2
흥미로운 점은 this._super("go1")
클래스 A에서 적중 될 때까지 클래스 계층 구조 를 스캔 하라는 클래스 C의 호출입니다 . 다른 솔루션은이를 수행하지 않습니다.
PS 조회 className
캐싱을 사용하려면 클래스 정의 항목의 주석 처리를 제거하십시오 _super
. (이러한 클래스 이름은 응용 프로그램에서 고유하다는 가정입니다.)
이것을 호출하고 싶다면 ._super (); 함수 이름을 인수로 전달하지 않고
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));
}
이 플러그인을 더 잘 사용하십시오 : https://github.com/lukasolson/Backbone-Super
테스트되지는 않았지만 원래 방법을 캐시 할 수 있다고 생각합니다.
var MyModel = Backbone.Model.extend({
origclone: Backbone.Model.clone,
clone: function(){
origclone();//calling the original clone method
}
});
내 요점에서 backbone._super.js : 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;
}));
부모 클래스가 정확히 무엇인지 모르는 경우 (다중 상속 또는 도우미 함수가 필요한 경우) 다음을 사용할 수 있습니다.
var ChildModel = ParentModel.extend({
initialize: function() {
this.__proto__.constructor.__super__.initialize.apply(this, arguments);
// Do child model initialization.
}
});
도우미 기능 :
function parent(instance) {
return instance.__proto__.constructor.__super__;
};
var ChildModel = ParentModel.extend({
initialize: function() {
parent(this).initialize.apply(this, arguments);
// Do child model initialization.
}
});
인스턴스화 중에 부모 클래스를 옵션으로 전달합니다.
BaseModel = Backbone.Model.extend({
initialize: function(attributes, options) {
var self = this;
this.myModel = new MyModel({parent: self});
}
});
그런 다음 MyModel에서 다음과 같은 부모 메서드를 호출 할 수 있습니다.
this.options.parent.method(); Keep in mind this creates a retain cycle on the two objects. So to let the garbage collector do it's job you would need to manually destroy the retain on one of the objects when finished with it. If you're application is pretty large. I would encourage you to look more into hierarchal setups so events can travel up to the correct object.
2 functions below, one requires you pass in the function name, the other can "discover" which function we want the super version of
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);
},
});
Here is how I would do this:
ParentClassName.prototype.MethodToInvokeName.apply(this);
so for your example this is:
Model.prototype.clone.apply(this)
참고URL : https://stackoverflow.com/questions/8596861/super-in-backbone
'Nice programing' 카테고리의 다른 글
고유 값 계산 (0) | 2020.10.23 |
---|---|
여러 줄 bash 코드를 터미널에 붙여넣고 한 번에 실행하려면 어떻게해야합니까? (0) | 2020.10.23 |
파이썬에서 목록을 공백이있는 문자열로 어떻게 변환합니까? (0) | 2020.10.23 |
IE의 CSS 회전 속성 (0) | 2020.10.22 |
NSString을 NSInteger로 변환 하시겠습니까? (0) | 2020.10.22 |