我有一堆函数(实际上是类的方法),我正在编写一个方法来记录与数组中其他方法的交互。 例如:
foo = Base.extend ({
a : function (a1,a2){
....
},
b:function(b1,b2){
...
},
history : function(){ ... }
})
为了简化历史记录方法,我想读取可选参数的名称并将它们添加到数组中,例如,如果调用方法a,我想记录a1,a2 ...... 所以基本上,有没有办法在javascript中读取数组的可选参数列表的名称?
这是代码:
var element = Base.extend({
constructor : function() {
if(arguments.length==1){
...
}else{
...
}
},
setLocation : function (top, left){
oldArgs = [this.top,this.left];
this.top = top;
this.left = left;
return(oldArgs);
},
setAspects : function (width, height){
oldArgs = [this.width,this.height]
this.width = width;
this.height = height;
return(oldArgs);
},
draw : function (page){
...
},
delet : function () {
...
},
$ : function(method,args){
var oldArgs = this[method].apply(this,args);
this.history(method,oldArgs);
Nx.pages[this.page].modified = true;
},
history : function (method,args){
Nx.history[Nx.history.length]=[this.id,method,args]
}
})
所以在这个类中,如果我想调用任何方法,我将通过$方法传递它,它将调用history方法,到目前为止我所做的是例如在setLocation方法中它将返回旧的参数,我将在我的数组Nx.history中对它们进行编辑,但是更方便的是在方法中对所有这些“返回”调用进行分解,并在$方法中添加一行,该行读取预期参数的名称。方法,并将其发送到历史方法,所以像这样:
$ : function(method,args){
this[method].apply(this,args);
**var oldArgs = this[method].arguments // get the list of argument names here
$.each(oldArgs, function(value) { Args[Args.length] = this.value //get the stored value in the class
})
this.history(method,Args); // and pass it to the history**
Nx.pages[this.page].modified = true;
}
答案 0 :(得分:2)
这个较新版本的想法是预先定义要为对象记录的属性。这是一个重复级别,但它只是一次性的事情。然后,在构造函数中,为每个属性创建属性设置器。设置者在设置属性的同时做了一些工作。它将参数名称和值压入堆栈,并分配属性。 $
方法应该调用调用适当的方法。调用完成后,将使用该函数中设置的参数填充堆栈。弹出该堆栈中的每个参数,直到堆栈为空。然后使用方法名称调用历史记录,以及刚刚从堆栈中弹出的参数。如果这没有任何意义,请告诉我,我可能要更好地说出来。
这是一个用MooTools编写的代码示例,它与您的Base类略有相似。
var Device = new Class({
_properties: ['top', 'left', 'width', 'height'],
_parameterStack: [],
initialize: function() {
this._createPropertyAccessors();
},
_createPropertyAccessors: function() {
this._properties.each(function(property) {
Object.defineProperty(this, property, {
enumerable: true,
configurable: true,
set: function(value) {
var o = {};
o[property] = value;
// push the parameter onto the stack
this._parameterStack.push(o);
}.bind(this)
});
}.bind(this));
},
// method stays unchanged
setLocation: function(top, left) {
this.top = top;
this.left = left;
},
setAspects: function(width, height) {
this.width = width;
this.height = height;
},
// dispatches call to method
// pops off the entire stack
// passed method name, and emptied stack arguments to history
$: function(method, args) {
this[method].apply(this, args);
var argsStack = [];
while(this._parameterStack.length) {
argsStack.push(this._parameterStack.pop());
}
this.history(method, argsStack);
},
history: function(method, args) {
console.log("%s(%o) called", method, args);
}
});
传递给JavaScript函数的参数可以通过名为arguments
的类似数组的对象访问,该对象可用于所有函数。
调用history
时,将arguments
对象传递给它。
a: function(a1, a2) {
this.history.apply(this, arguments);
}
然后将调用 history
,就好像它是使用两个参数调用this
作为基础对象 - foo
,除非您使用不同的上下文调用它。
我不确定Base
如何发挥作用。你必须在这里详细说明Base
的作用。
这是一个简单的例子:
var foo = {
a: function(a1, a2) {
this.history.apply(this, arguments);
},
history: function() {
console.log("history received " + arguments.length + " arguments.");
}
};
foo.a("hello", "world"); // history received 2 arguments
另请注意,尽管此处a
有两个命名参数,但我们仍然可以传递任意数量的参数,并且所有这些参数将依次传递给history
方法。我们可以将a
称为:
foo.a(1, 2, 3); // history received 3 arguments
答案 1 :(得分:2)
我不是100%肯定你要求的 - 一种提取函数形式参数名的方法吗?
我不知道这是否可行,但是你能解析函数的字符串表示来提取参数名吗?
这可能是一个非常蹩脚的解决方案,但您可以做类似的事情:
function getArgNames(fn) {
var args = fn.toString().match(/function\b[^(]*\(([^)]*)\)/)[1];
return args.split(/\s*,\s*/);
}
答案 2 :(得分:1)
这样的事情应该有效。如果要访问已使用的参数,可以遍历包含参数列表的foo.history数组。
var foo = {
storeArgs: function (fn) {
return function() {
this.history += arguments
return fn.apply(null, arguments);
}
},
a: storeArgs(function(a1, a2) {
alert(a1+a2);
}),
history: []
};
我看了你的最新帖子。你是什么意思“名字?”变量名称?例如,如果某人调用了a(1337)
,您是否希望将["a1"]
添加到数组中?如果a(1337, 132)
被调用,["a1", "a2"]
会被添加吗?我认为没有任何理智的方法可以做到这一点。
这是我能做的最好的事情。使用storeArgs函数定义函数时,必须包含参数名列表。
var foo = {
storeArgs: function (params, fn) {
return function() {
var arr = [];
for (var i = 0; i < arguments.length; i++) {
arr.push(params[i]);
}
this.history += arr;
return fn.apply(null, arguments);
}
}
a: storeArgs(["a1", "a2"], function(a1, a2) {
alert(a1+a2);
}),
history: []
};
让我知道它是否有效。
答案 3 :(得分:0)
这适用于IE,但我不确定其他浏览器......
Function.prototype.params = function() {
var params = this.toString().split(/(\r\n)|(\n)/g)[0];
params = params.trim().replace(/^function.*?\(/, "");
params = params.match(/(.*?)\)/)[1].trim();
if (!params) {
return([]);
}
return(params.split(/, /g));
};
function Test(a, b) {
alert(Test.params());
}
Test();