1
var Model = function(client, collection) {
  this.client = client;
  this.collection = collection;
};

Model.prototype = {
  constructor: Model,
  getClient: function(callback) {
    this.client.open(callback);
  },
  getCollection: function(callback) {
    var self = this;

    this.getClient(function(error, client) {
      client.collection(self.collection, callback);
    });
  },
  extend: function(key, fn) {
    var self = this;

    this[key] = function() {
      fn.call(self); // A
    };
  }
};

我想要实现的是我可以“扩展”模型的功能。

var userModel = new Model(client, 'users');
userModel.extend('create', function(data, callback) {
  this.getCollection(function(error, collection) {
    collection.insert(data, { safe: true }, function(error, doc) {
      callback.call(doc);
    });
  });
});

userModel.create({ fullName: 'Thomas Anderson' }, function() {
  console.log(this); // { _id: '123456789012345678901234', fullName: 'Thomas Anderson' }
});

在 A 的某个地方,我必须进行参数传递,自定义“创建”函数(数据和回调)的参数计数是可变的。

这可能吗?如果可以,怎么办?

4

4 回答 4

3

是的!您想使用.apply方法而不是.call方法。两者都应用上下文,但该.apply方法需要一个数组作为参数 - 或参数集合本身!

extend: function(key, fn) {
    var self = this;

    this[key] = function() {
      fn.apply(self,arguments); // the special arguments variable is array-like
    };
  }
于 2012-10-08T20:47:04.877 回答
0

在@zetlen 评论之后还有一件事,函数的范围(this)是函数调用的最后一个点后面的内容,在这种情况下:

userModel.create();

该函数的“this”变量将是“userModel”。

所以只要你用“modelname.functionName()”调用它,你就不需要传递自我:

extend: function(key, f) {
    this[key] = f;
}

(要不就)

userModel.someMethod = function() { ... };

然后,当您调用 modelkey 时,您会将参数直接传递给函数,并且您将拥有所需的范围。

var userModel = new Model(...);
userModel.extend('hi', function(arg) {
  this === userModel;
  arg === 42;
});
userModel.hi(42);

看看这个小提琴看看它:http: //jsfiddle.net/NcLQB/1/

但是请记住,如果您取出模型的功能,它将不再具有范围,如果您这样做,您最好像您的代码片段一样继续这样做。

var funct = userModel.hi;
funct(); // this === global!!!

// OR

// When the event is fired the scope isn't userModel
otherThing.on('someEvent', userModel.hi);
于 2012-10-08T21:02:14.443 回答
0

除非您有任何隐藏的原因在原型中创建extend方法并强制执行范围,否则您可以将方法分配给创建的实例:

var userModel = new Model(client, 'users');
userModel.create = function(data, callback) {
  this.getCollection(function(error, collection) {
    collection.insert(data, { safe: true }, function(error, doc) {
      callback.call(doc);
    });
  });
});

它会更快,更干净,您不必担心通过另一个函数传递参数。

通过封装来强制执行范围(或上下文)并不总是一件好事,因为您正在限制语言的动态。

于 2012-10-08T21:08:50.597 回答
0
 this[key] = function() {
      fn.apply(self, arguments);
    };
于 2012-10-08T20:48:57.873 回答