3

假设我想要这个 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.createAPI。

有没有设计模式来实现这一点?

4

3 回答 3

1

你不能todo.model像你写的那样使用原型模式,因为model是.todo

我认为你需要:

  1. 一个新Model对象,您可以在其上使用原型模型。

  2. Todo构造函数中,创建一个Model对象。理想情况下,使用只读“getter”函数来允许访问该模型对象,但不会被覆盖。

于 2012-10-22T07:30:00.253 回答
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.

于 2012-10-22T09:02:02.157 回答
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 的新浏览器中的本机实现不冲突。

于 2012-10-22T07:32:35.940 回答