我编写了以下例程来对option
中的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]);
}
使用Firefox作为Greasemonkey脚本的一部分,它可以正常工作。但是,在使用和不使用TamperMonkey的Chrome中,我都会这样做:
Uncaught Error: NOT_FOUND_ERR: DOM Exception 8
SortSelect:125
正如Javascript调试器的典型情况一样,错误行号是完全错误的,所以很难确切地说明为什么会破坏它以及在哪里。我愿意接受有关代码为什么会被淘汰或者有效调试它的方法的建议(我是Chrome的新手)。感谢。
答案 0 :(得分:2)
你想用这段代码做什么?
while (select.options.length > 0)
select.options[0] = null;
如果答案是你要清除所有选择选项,这似乎很危险。我可以看到这很容易成为一个无限循环。
在我看来,这样会更安全:
for (var i = select.options.length - 1; i > 0; i--) {
select.remove(i);
}
然后,有一个select.options.add()
方法可以将它们添加回来。
仅供参考,在阵列或伪阵列上使用此构造也被认为是冒险的做法:
for (var i in select.options)
for (var i in tmpAry)
因为除了数组元素之外,它还可以获取已添加到对象的属性。
更多打字,但更安全:
for (var i = 0, len = tmpAry.length; i < len; i++) {
// code here
}
答案 1 :(得分:2)
您应该使用索引迭代 options 集合,而不是for..in循环。以下内容:
for (var i in select.options) {
tmpAry[i] = select.options[i];
应该是:
var options = select.options;
for (var i=0, iLen=options.length; i<iLen; i++) {
tmpAry[i] = options[i];
}
您可能从选项集合中获取非选项元素的属性,例如length。
您也不应该为选项指定“null”。如果要删除所有选项,只需将选项的长度设置为零:
var options.length = 0;
最后,您应该使用索引迭代 tmpAray ,因为for..in 不会在每个浏览器中以相同的顺序返回选项,并且可能返回非数字如果存在可枚举属性,使用索引。此外,您只需将选项分配回select的选项集合,就不需要 appendChild :
select.options.length = 0;
for (var i=0, iLen=tmpAry.length; i<iLen; i++) {
select.options[i] = tmpAry[i];
}
如果你没有删除任何选项,你应该能够按新顺序分配它们,但有些浏览器无法处理,所以最好先删除它们。
请注意,虽然select element的options属性是readonly,但options collection的属性却不是。{您可以直接为它们分配值(应该是对选项元素的引用)。
答案 2 :(得分:1)
这些行可能导致无限循环或访问冲突:
while (select.options.length > 0)
select.options[0] = null;
此外,您不需要删除节点并重新插入它们; appendChild()
works fine in all browsers to move nodes around
因此,此代码将起作用,并且应该比删除和重新创建节点(也可以删除任何事件侦听器)更有效。 :
function SortSelect (select)
{
var tmpAry = [];
for (var J = select.options.length - 1; J >= 0; --J)
tmpAry.push (select.options[J] );
tmpAry.sort ( function (opta, optb) {
if (opta.id > optb.id) return 1;
if (opta.id < optb.id) return -1;
return 0;
} );
while (tmpAry.length) {
select.appendChild ( document.getElementById (tmpAry[0].id) );
tmpAry.shift ();
}
}