context
我创建了一个数组docket
,用于在用户单击画布空间时跟踪坐标。在主程序循环期间,数组将由绘制功能扫描,以便可以看到选定的像素。最初,在我的事件侦听器中,我使用的是push( )
方法,但后来我意识到我想要一种切换像素的方法。
代码说明
所以我在Array.prototype
中添加了一个方法poke( )
,如下所示,它允许我将整个docket
数组推送到局部数组param.array
并将触发坐标分配给局部变量param.entry
。 然后将entry
推送到array
中,array
由主poke( )
循环进行处理,以确保没有重复的值。如果找到匹配项,则两个元素都被湮灭,param.array
被返回到顶部,最终将docket
缩小 1;如果未找到匹配项,则不会湮灭任何元素,param.array
将返回到顶部,最终将docket
扩展为 1。
主要问题:示例 1
无论如何,由于该方法是当前编写的,因此必须这样调用它:
docket.poke( docket, e.key );
注意:为简单起见,我使用了键盘键值。
Array.prototype.poke = function( a, b ) {
var bool = { }, i = { }, param = { };
param.array = a; param.entry = b;
//
param.array.push( param.entry );
i.len = param.array.length;
i.end = i.len - 1;
//
for ( i.cur = 0; i.cur < i.len; i.cur++ ) {
bool.match = param.array[ i.cur ] == param.array[ i.end ];
bool.nSelf = !( i.cur == i.end );
//
if ( bool.match && bool.nSelf ) {
param.array.splice( i.end, 1 );
param.array.splice( i.cur, 1 );
//
i.end -= 2;
i.len -= 2;
}
}
//
return param.array;
}
这似乎有点多余,但它提供了两个关键优势。首先是可读性和美学。能够明显地将docket
的内容传递给本地数组进行处理,然后明显地将结果返回到顶部,我认为这对理解非常有帮助。其次,此示例和下一个示例都使用一种令人困惑的真值检验来过滤掉重复值检测中的误报。不过,这个例子没有。它可以很容易地重写,以使用紧凑的、无废话的 for 循环将param.array
中的每个元素与param.entry
进行比较。
主要问题:示例 2
docket.poke( e.key );
是少冗余和更理想的方法。这是我的代码。
Array.prototype.poke = function( a ) {
var bool = { }, entry = a, i = { };
//
this.push( entry );
i.len = this.length;
i.end = i.len - 1;
//
for ( i.cur = 0; i.cur < i.len; i.cur++ ) {
bool.match = this[ i.cur ] == this[ i.end ];
bool.nSelf = !( i.cur == i.end );
//
if ( bool.match && bool.nSelf ) {
this.splice( i.end, 1 );
this.splice( i.cur, 1 );
//
i.end -= 2;
i.len -= 2;
}
}
}
如您所见,这消除了调用中的冗余,但它牺牲了方法的一些可读性,更重要的是,牺牲了使用我上面提到的简单比较真正精简代码的机会。
所以现在我想知道是否有一些不太明显的方式,我错过了,它可以让我将数组的全部内容传递给局部变量,而不必首先将它们作为其自己的方法的参数传入。
有什么想法吗?
如果要将数组作为参数传递,则没有理由在原型上定义该方法。一个普通的函数就可以了。
代码的第二个版本确实具有以下优点:您可以将该方法应用于给定数组,而不是将数组传递给函数。
但是,在以下情况下,可以简化代码:
- 只有在确定元素尚未出现在数组中后,您才会添加该元素
- 您将使用
indexOf
:
Array.prototype.toggle = function(value) {
var index = this.indexOf(value);
if (index > -1) {
this.splice(index, 1);
} else {
this.push(value);
}
}
var a = [4,2,5,8];
a.toggle(2);
console.log(a.join());
a.toggle(2);
console.log(a.join());
注意:我个人觉得这个名字toggle
比poke
更有说服力。
还要考虑Set
的幂:它将在恒定时间内找到一个现有成员(而数组实现需要线性时间(,并且还能够在恒定时间内删除它。因此,如果您愿意为此使用数组以外的其他东西,请Set
.
Set.prototype.toggle = function(value) {
if (!this.delete(value)) this.add(value);
}
var a = new Set([4,2,5,8]);
a.toggle(2);
console.log([...a].join());
a.toggle(2);
console.log([...a].join());