假设我想让这个API作为应用程序的示例:
var db = new Database('db-name'); // DB connection
var todo = new Todo(db); // New "Todo" and pass it the DB ref
// I want this API:
todo.model.create('do this', function (data) {
console.log(data);
});
我现在设置如下:
function Todo (storage) {
this.storage = storage;
};
Todo.prototype.model = {
create: function (task, callback) {
// The problem is "this" is Todo.model
// I want the "super", or Todo so I can do:
this.storage.save(task, callback);
}
}
因此,如果您看到评论,问题是this
内部的“model.create
”显然引用了Todo.model
,但我需要它来抓住“super
}”。
我能想到的最好的是:
Todo.prototype.model = function () {
var self = this;
return {
create: function (task, callback) {
// The problem is "this" is Todo.model
// I want the "super", or Todo so I can do:
self.storage.save(task, callback);
}
}
}
但这两个都不是很好。最大的问题是我不希望在单个对象(第一个示例)或函数(第二个)中的model
上拥有所有方法。我希望能够从模型def中取出它们。其次,我想要todo.model.create
API。
是否有设计模式来实现这一目标?
答案 0 :(得分:1)
由于todo.model
是model
的属性,因此您无法使用todo
原型模式。
我认为你需要:
一个新的Model
对象,可以使用原型模型。
在Todo
构造函数中,创建一个Model
对象。理想情况下,使用只读“getter”函数来允许访问该模型对象,但不能覆盖该模型对象。
答案 1 :(得分:1)
使用bind
,您可以执行以下操作:
function Todo (storage) {
this.storage = storage;
this.model = {};
var methodNames = Object.keys(TodoModel);
for(var i = 0; i < methodNames.length; ++i) {
var methodName = methodNames[i];
var method = TodoModel[methodNames];
model[methodName] = method.bind(this);
}
};
var TodoModel = {
create: function(task, callback) {
// Note that when this method is called using Todo.model.create,
// 'this' will point to the Todo instance.
this.storage.save(task, callback);
}
};
function test(storage) {
var todo = new Todo(storage);
var task = {};
todo.model.create(task, function(err, savedTask) {
// ...
});
}
TodoModel
基本上是一张地图,因此您可以将其替换为地图集合,您将不再需要致电Object.keys
。
答案 2 :(得分:0)
您可以在构造函数中设置model
,如下例所示:
function Todo (storage) {
var self = this;
this.storage = storage;
this.model = {
create: function(task, callback) {
self.storage.save(task, callback);
}
};
};
或者,您可以使用bind,但我认为它会使事情变得更加复杂,因为您必须找到适用于旧浏览器的实现,并且它不会与支持EcmaScript的新浏览器中的本机实现冲突5。