JScript内置对象Array中元素的删除问题

    我们知道JScript给我们提供了一个内置的数组对象Array。Array对象除了提供了constructor、length和prototype外,还默认提供了13个方法:concat、join、pop、push、reverse、shift、slice、sort、splice、toLocaleString、toString 、unshift和valueOf,可是没有提供delete方法

    要是熟悉JavaScript的话,会马上说,系统提供了一个delete操作,可以用来删除数组中的元素。对,JS系统里确实有一个delete可以删除数组中的元素。可是这个删除很难用,它确实可以删除元素,可是它却不更新Array对象的元素计数器。例如我们执行:

var ary = ['a', 'b', 'c'];
delete ary[1];

    如果正确的执行删除后,我们希望会得到一个新的数组,他有两个元素['a', 'c'],长度为2。可是执行完后我们确实是得到了两个元素['a', 'c']的数组,可是这个新数组的长度ary.length居然还是3!。同时我们执行ary.toString()将得到"a,,c",这也表明数组的计数器还是3,因为Array的toString()实际上执行的是Array.join(',')。

    这样的删除在我们使用for( ; ; )遍历数组的时候,将会非常的郁闷,我们可能很容易就可能被一个undefined的值搞死掉了。那么怎么才能获得删除数组元素后同步数组的大小呢?由于Array本身提供的pop和shift两个函数可以"真正的"删除数组的元素,所以我们可以使用它们来自己扩充一个remove函数。

    但是pop和shift只能从数组的两端删掉元素,所以我们在删除之前需要对数组做一些整理,实现remove方法的代码如下:

Array.prototype.remove = function(obj)
{
    
for ( var i=0 ; i < this.length ; ++i )
    {
        
if ( this[i] == obj )
        {
            
if ( i > this.length/2 )
            {
                
for ( var j=i ; j < this.length-1 ; ++j )
                {
                    
this[j] = this[j+1];
                }
                
this.pop();
            }
            
else
            {
                
for ( var j=i ; j > 0 ; --j )
                {
                    
this[j] = this[j-1];
                }
                
this.shift();
            }    
            
break;
        }
    }
};

    移动整理数组的目的只是为了删除元素后不改变剩余元素的彼此相对位置,否则只用把需要删除的元素swap到两端pop或shift以下就可以了。

posted on 2005-01-07 21:51 birdshome 阅读(2712) 评论(10) 编辑 收藏

评论

#1楼  回复 引用   

splice就可以remove

ary.splice(1, 1);
2005-01-07 22:36 | 问题男

#2楼[楼主]  回复 引用 查看   

very good,这下可以把remove优化为:
Array.prototype.remove = function(obj)
{
    
for ( var i=0 ; i < this.length ; ++i )
    {
        
if ( this[i] == obj )
        {
            
this.splice(i, 1); 
            
break;
        }
    }
};
2005-01-07 22:51 | birdshome      

#3楼  回复 引用 查看   

高,做JavaScript也可以做成这种境界,收藏之~
2005-01-10 08:41 | Boler      

#4楼  回复 引用   

这里是有问题的~~其实没必要实现remove/delete方法。

非要实现的话,一行代码就OK。
Array.prototype.remove = [].splice;

当然,要实现
function remove(obj) {}
这样的接口,那么birdshome提供的是最正确的代码。
2005-01-11 10:31 | Aimingoo[未注册用户]

#5楼  回复 引用   

@Aimingoo
如果Array没有附加额外的原型方法,对于系统delete那个缺陷确实不用太care,可以用 for ( in ) 就把它绕过去了
不过有两个问题:
一是for(in)效率比for( ; ;)低(前面我有文章说到);
二是如果附加了别的原型方法,每次ary[key]就要做判断。
2005-01-11 10:44 | birdshome

#6楼  回复 引用   

Array.prototype.remove = function(position) {
if(position > this.length || position < 0) {
throw "Out of the array range.";
}
for(var i=position; i<this.length-1; i++) {
this[i] = this[i+1];
}
this.length = this.length-1;
}
帮忙看看,这样行不行?
2005-12-16 10:01 | icyker[未注册用户]

#7楼[楼主]  回复 引用 查看   

@icyker
有两个地方有问题,一是 position > this.length 应该是 position >= this.length;
二是 throw "Out of the arry range" 应该是 throw new Error("Out of the array range.")。
2005-12-16 10:30 | birdshome      

#8楼  回复 引用   

@birdhome
能加我不,我的msn: icyker at gmail dot com
为什么非得new Error()呢? 我看微软自己的代码里也有时不用的阿!
2005-12-16 16:05 | icyker[未注册用户]

#9楼  回复 引用   

Array.prototype.indexOf = function(p_var)
{ for (var i=0; i<this.length; i++)
{ if (this[i] == p_var)
{ return(i);}
}
return(-1);}
Array.prototype.remove = function(o)
{ var i = this.indexOf(o); if (i>-1) this.splice(i,1); return (i>-1)
}
这是start.com msncore.js里的
2005-12-16 16:07 | icyker[未注册用户]

#10楼[楼主]  回复 引用 查看   

@icyker
splice不是ECMAScript规范里的方法,不过只做IE支持倒也没有什么问题。
至于为什么要new Error?这里也不是必须,虽然 throw 一个字符串也能运行,不过在一个健全的错误处理场景里面,是用该是 new Error("error info") 或者 new Error(errorNumber, errorInfo) 的。
2005-12-16 16:39 | birdshome      

导航

公告

  原创技术文章和心得,转载必须注明来源"博客园"!
  贴子以"现状"提供,且没有任何担保,同时也没有授予任何权利。
昵称:birdshome
园龄:7年10个月
荣誉:推荐博客
粉丝:73
关注:3

搜索

 

常用链接

我的标签

随笔分类(337)

文章分类(147)

相册

Ex-Colleagues

常用链接

兄弟情深

积分与排名

  • 积分 - 3145044
  • 排名 - 6

最新评论

阅读排行榜

推荐排行榜