元素排序例程在 Firefox 中有效,但在 Chrome 中崩溃
我编写了以下例程来对 select
中的 option
元素进行排序:
function SortSelect(select)
{
var tmpAry = new Array();
for (var i in select.options)
tmpAry[i] = select.options[i];
tmpAry.sort(function(opta, optb)
{
if (opta.id > optb.id) return 1;
if (opta.id < optb.id) return -1;
return 0;
});
while (select.options.length > 0)
select.options[0] = null;
for (var i in tmpAry)
select.appendChild(tmpAry[i]);
}
作为 Greasemonkey 脚本的一部分,它在 Firefox 中运行得很好。然而,在 Chrome 中,无论有没有 TamperMonkey,我都会得到这样的信息:
Uncaught Error: NOT_FOUND_ERR: DOM Exception 8
SortSelect:125
正如 Javascript 调试器的典型情况一样,错误行号完全错误,因此很难准确确定为什么会出现问题以及在哪里出现问题。我愿意接受有关代码为何出错或有效调试代码的方法的建议(我是 Chrome 的新手)。谢谢。
I've written the following routine to sort the option
elements within a select
:
function SortSelect(select)
{
var tmpAry = new Array();
for (var i in select.options)
tmpAry[i] = select.options[i];
tmpAry.sort(function(opta, optb)
{
if (opta.id > optb.id) return 1;
if (opta.id < optb.id) return -1;
return 0;
});
while (select.options.length > 0)
select.options[0] = null;
for (var i in tmpAry)
select.appendChild(tmpAry[i]);
}
It works just fine with Firefox as part of a Greasemonkey script. However, in Chrome, both with and without TamperMonkey, I get this:
Uncaught Error: NOT_FOUND_ERR: DOM Exception 8
SortSelect:125
As is typical for Javascript debuggers, the error line number is totally wrong, so it's difficult to pin down exactly why this is breaking and where. I'm open to suggestions as to why the code is bugging out or ways to effectively debug it (I'm new to Chrome). Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您应该使用索引而不是 for..in 循环来迭代 options 集合。以下内容:
应该是:
您可能从选项集合中获取不是选项元素的属性,例如长度。
您也不应该将“null”分配给选项。如果要删除所有选项,只需将 options 的长度设置为零:
最后,您应该使用索引迭代 tmpAray,因为 for..in 不会在每个浏览器中以相同的顺序返回选项,并且可能返回非数字可枚举属性(如果有),使用索引。另外,您可以将选项分配回选择的选项集合,不需要appendChild:
如果您不删除任何选项,则应该能够按照新顺序分配它们,但有些浏览器无法处理该问题,因此最好先删除它们。
编辑
请注意,虽然 select 元素的 options 属性 是只读的,选项集合的属性 是 不是。您可以直接向它们分配值(应该是对选项元素的引用)。
You should iterate over the options collection using an index, not a for..in loop. The following:
should be:
You are likely getting properties from the options collection that aren't option elements, such as length.
You also should not assign "null" to an option. If you want to remove all the options, just set the length of options to zero:
Finally, you should iterate over tmpAray using an index since for..in will not return the options in the same order in every browser and may return non-numeric enumerable properties if there are any, use an index. Also, you can just assign the option back to the select's options collection, there is no need for appendChild:
If you are not removing any options, you should be able to just assign them in the new order, but some browsers can't handle that so removing them first is best.
Edit
Note that while the options property of a select element is readonly, the properties of an options collection are not. You can assign values (which should be references to option elements) directly to them.
你想用这段代码做什么?
如果答案是您试图清除所有选择的选项,那似乎很危险。我可以看出这很容易成为无限循环。
在我看来,这会更安全:
然后,有一个
select.options.add()
方法可以将它们添加回来。仅供参考,在数组或伪数组上使用此构造也被认为是有风险的做法:
因为除了数组元素之外,它还可以获取已添加到对象的属性。
更多打字,但使用更安全:
What are you trying to do with this piece of code?
If the answer is you're trying to clear all the select options, that seems dangerous. I could see how this could easily be an infinite loop.
It looks to me like this would be a lot safer:
Then, there's an
select.options.add()
method for adding them back.FYI, it is also considered risky practice to use this construct on arrays or pseudo arrays:
as that can pick up properties that have been added to the object in addition to just array elements.
More typing, but safer to use:
这些行可能会导致无限循环或访问冲突:
此外,您不需要删除节点并重新插入它们;
appendChild()
在所有浏览器中都可以正常移动节点。因此,此代码将起作用,并且应该比删除和重新创建节点(这也可能会破坏任何事件侦听器)更有效。 :
在 jsFiddle 上查看它的实际效果。
These lines can cause an infinite loop or an access violation:
Also, you do not need to delete the nodes and reinsert them;
appendChild()
works fine in all browsers to move nodes around.So, this code will work and should be more efficient than removing and recreating nodes (which can also trash any event listeners). :
See it in action at jsFiddle.