JavaScript扩展parameter passing

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

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

 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的某处,我必须做parameter passing,自定义“创build”函数(数据和callback)的参数数量是可变的。

这是可能的,如果是这样的话?

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

 extend: function(key, fn) { var self = this; this[key] = function() { fn.apply(self,arguments); // the special arguments variable is array-like }; } 
  this[key] = function() { fn.apply(self, arguments); }; 

在@zetlen注释之后还有一件事,函数的作用域(this)是函数调用的最后一个点的后面,在这种情况下:

 userModel.create(); 

该函数的“this”variables将是“userModel”。

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

 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/

但是,请记住,如果你拿出模型的function,将不再有范围,如果你这样做,你最好继续做你的代码片段。

 var funct = userModel.hi; funct(); // this === global!!! // OR // When the event is fired the scope isn't userModel otherThing.on('someEvent', userModel.hi); 

除非在原型中创buildextend方法并强制执行范围有任何隐藏的原因,否则只需将该方法分配给创build的实例即可:

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

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

通过封装来实现一个范围(或上下文)并不总是一件好事,因为你限制了语言的dynamic。