我有一些看起来像这样的代码:
function StrippedExample(i1, i2, i3, i4, i5, i6, i7, i8) {
this.i = [];
for (var i=1,j=0 ;i<9;i++) {
var k = eval("i"+i);
if (k > 0) {
this.i[j++] = k;
}
}
}
FireBug profiler声称第二个最长的函数是eval(),占运行时间的近6%。
Everyone says eval is EVIL(和坏的一样)和慢(我发现),但我不能做任何其他事情 - 服务器只是将数据从数据库中拉出并推送到浏览器。
我有什么替代品?我可以像在服务器上做的那样做,但这只会将负担转移到链条上方。我无法更改数据库布局,因为所有内容都挂钩到这8个变量,这是一项艰巨的任务。
function StrippedExample(i1, i2, i3, i4, i5, i6, i7, i8) {
var args = [i1, i2, i3, i4, i5, i6, i7, i8]; // put values in an array
this.i = [];
for (var i=0,j=0 ;i<8;i++) { // now i goes from 0-7 also
var k = args[i]; // get values out
if (k > 0) {
this.i[j++] = k;
}
}
}
上面的代码可以进一步简化,我只是做了最小的改变,以摆脱eval
。你可以摆脱j
,例如:
function StrippedExample(i1, i2, i3, i4, i5, i6, i7, i8) {
var args = [i1, i2, i3, i4, i5, i6, i7, i8];
this.i = [];
for (var i = 0; i < args.length; i++) {
var k = args[i];
if (k > 0) { this.i.push(k); }
}
}
是等价的。或者,使用内置的arguments
对象(以避免在两个地方放置参数列表):
function StrippedExample(i1, i2, i3, i4, i5, i6, i7, i8) {
this.i = [];
for (var i = 1; i < arguments.length; i++) {
var k = arguments[i];
if (k > 0) { this.i.push(k); }
}
}
即使你没有过滤列表,你也不想做像this.i = arguments
这样的事情,因为arguments
不是真正的数组;它有一个你不需要的callee
属性,并且缺少i
中可能需要的一些数组方法。正如其他人所指出的,如果你想快速将arguments
对象转换为数组,你可以使用这个表达式:
Array.prototype.slice.call(arguments)
您可以使用它而不是上面的var args = [i1, i2 ...
线。
您只是从函数8参数创建一个数组,删除小于或等于零的数组。
以下代码是等效的,它适用于任意数量的参数:
function StrippedExample() {
var args = [];
for (var i = 0; i < arguments.length; i++) {
if (arguments[i] > 0) {
args.push(arguments[i]);
}
}
//...
}
将数组传递给函数的一种替代方法,而不是单个参数:
StrippedExample([3, 1, 4, 1, 5, 9, 2, 6])
然后你的代码将是:
function StrippedExample(inArray) {
this.i = [];
for (var i=0,j=0 ;i<inArray.length;i++) {
var k = inArray[i];
if (k > 0) {
this.i[j++] = k;
}
}
}
如果你真的需要传入单独的参数,你可以使用你的arguments
数组访问它们,这个数组就像一个数组(虽然它不是真的;并非所有的数组方法都可以使用它),它暴露了所有传递的参数在你的功能;在这种情况下甚至不需要声明它们,但是包含一个注释可以很好地形成一个注释,表明您希望代码用户有哪些类型的参数:
function StrippedExample(/*i1, i2, i3, i4, i5, i6, i7, i8*/) {
this.i = [];
for (var i=0,j=0 ;i<arguments.length;i++) {
var k = arguments[i];
if (k > 0) {
this.i[j++] = k;
}
}
}
如果你保证只有8个元素,那么你可以使用8
代替inArray.length
或arguments.length
;我决定在我的示例中使用更通用的版本,以防对您有所帮助。
应该使用此代码来使用每个Javascript函数都可以访问的arguments
数组。
这不是eval
是邪恶的(它在Lisp中,所以它一定是好的)它只是一个黑客的标志 - 你需要一些工作而你强迫它。它向我尖叫“作者放弃了良好的编程设计,只是发现了一些有用的东西”。
function StrippedExample() {
this.i = [];
for (var i=1,j=0 ;i<arguments.length;i++) {
var k = arguments[i];
if (k > 0) {
this.i[j++] = k;
}
}
}
Eval替代方案:
exp = '1 + 1'
x = Function('return ' + exp)()
console.log(x)
鉴于存在固定数量的变量,您可以手动构建它们的数组并循环遍历它。但是如果你有一个可变数量的参数,一种方法是将变量作为数组传递给函数:
var args = Array.prototype.slice.call(arguments.callee.caller.arguments);
你的功能看起来像这样:
function StrippedExample() {
var args = Array.prototype.slice.call(arguments.callee.caller.arguments);
for(var i in args) {
if (args[i] > 0) {
this.i[j++] = args[i];
}
}
}
StrippedExample=(...a)=>a.filter(i=>i>0);
根本不需要使用eval来处理参数。