如何使用JavaScript创建此API并打破方法

时间:2021-07-09 20:44:29

Let's say I wanted to have this API for an example to do app:

假设我想让这个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);
});

I have it setup currently like:

我现在设置如下:

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);
  }
}

So, if you see the comment, the problem is that "this" inside of model.create is obviously referencing Todo.model, but I need it to grab the "super".

所以,如果你看到评论,问题是model.create中的“this”显然引用了Todo.model,但我需要它来抓住“超级”。

Best I could think of was:

我能想到的最好的是:

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);
    }
  }
}

But both of these aren't great. The biggest problem is that I don't want to have all my methods on model inside of a single object (1st example) or function (2nd). I want to be able to take them out from inside of the model def. Secondly, I'd like to have the todo.model.create API.

但这两个都不是很好。最大的问题是我不希望在单个对象(第一个示例)或函数(第二个)中使用模型上的所有方法。我希望能够从模型def中取出它们。其次,我想要todo.model.create API。

Is there a design pattern to achieve this?

是否有设计模式来实现这一目标?

3 个解决方案

#1


1  

You can't use the prototype pattern for todo.model as you've written it because model is a property of todo.

您不能在编写todo.model时使用原型模式,因为model是todo的属性。

I think you need:

我认为你需要:

  1. a new Model object, on which you can use the prototype model.

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

  2. in the Todo constructor, create a Model object. Ideally, use a read-only "getter" function to allow that model object to be accessed, but not overwritten.

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

#2


1  

Using bind, you can do something like this:

使用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) {
    // ...
  });
}

The TodoModel is basically a map, so you can replace it with a Map collection and you will no longer need to call Object.keys.

TodoModel基本上是一个地图,因此您可以用Map集合替换它,您将不再需要调用Object.keys。

#3


0  

You could set up the model in the constructor like in the following example:

您可以在构造函数中设置模型,如下例所示:

function Todo (storage) {
  var self = this;

  this.storage = storage;

  this.model = {
    create: function(task, callback) {
      self.storage.save(task, callback);
    }
  };
};

Alternatively, you could use bind, but I think that it would unnecessarily complicate things, because you must find an implementation that works on older browsers and it does not conflict with the native implementation in newer browsers that support EcmaScript 5.

或者,您可以使用bind,但我认为它会使事情变得更加复杂,因为您必须找到适用于旧浏览器的实现,并且它不会与支持EcmaScript 5的较新浏览器中的本机实现冲突。

#1


1  

You can't use the prototype pattern for todo.model as you've written it because model is a property of todo.

您不能在编写todo.model时使用原型模式,因为model是todo的属性。

I think you need:

我认为你需要:

  1. a new Model object, on which you can use the prototype model.

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

  2. in the Todo constructor, create a Model object. Ideally, use a read-only "getter" function to allow that model object to be accessed, but not overwritten.

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

#2


1  

Using bind, you can do something like this:

使用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) {
    // ...
  });
}

The TodoModel is basically a map, so you can replace it with a Map collection and you will no longer need to call Object.keys.

TodoModel基本上是一个地图,因此您可以用Map集合替换它,您将不再需要调用Object.keys。

#3


0  

You could set up the model in the constructor like in the following example:

您可以在构造函数中设置模型,如下例所示:

function Todo (storage) {
  var self = this;

  this.storage = storage;

  this.model = {
    create: function(task, callback) {
      self.storage.save(task, callback);
    }
  };
};

Alternatively, you could use bind, but I think that it would unnecessarily complicate things, because you must find an implementation that works on older browsers and it does not conflict with the native implementation in newer browsers that support EcmaScript 5.

或者,您可以使用bind,但我认为它会使事情变得更加复杂,因为您必须找到适用于旧浏览器的实现,并且它不会与支持EcmaScript 5的较新浏览器中的本机实现冲突。