2011-08-14 79 views
4
var down=function(a,b){alert(a)} 
Array.prototype.sort.call(table.tBodies[0].childNodes,down) 
Array.prototype.sort.call([0,1,2,3],down) 

爲什麼我沒有從第一個排序調用中收到警報?使用Array.prototype.sort.call對HTMLCollection進行排序

+0

也許'childNodes'是空的? – Mrchief

+0

不好意思,大量的childNodes可用於tBody [0] –

+0

test = table.tBodies [0] .childNodes [2] .childNodes [0] .innerHTML –

回答

7

轉換的NodeList到數組第一:

var elements = [].slice.call(table.tBodies[0].childNodes); 

,然後調用sort正常:

elements.sort(down); 

看來sort不能處理陣列狀對象。這可能是因爲NodeList未提供任何方法來更改列表,但sort將數組在原地排列

更新:欲瞭解更多信息,請從specification

執行調用的實現依賴序列的[[Get]] [[將]和[刪除]內部方法obj

我假設NodeList s沒有這些內部方法。但這只是一個假設。也可能是這是依賴於實現的。

我還建議您使用.children[MDN]而不是.childNodes來獲取元素節點。 更新:.rows[DOM Spec] @patrick建議。

+1

爲什麼會有幫助? ECMA-262將'slice' _and_'sort'定義爲通用函數,可以將其應用於任何具有適當屬性的任何東西。它會警告它可能不適用於宿主對象,但是爲什麼'slice'在DOM列表上比'sort'更好? –

+0

@Felix:或者使用'.rows'代替'.children'來提高兼容性。我想知道'.sort()'是不是'.slice()'的方式不允許像數組一樣的對象。編輯:關於你的更新,這是有道理的。 +1 – user113716

+3

@亨寧:查看我最新的更新。 [規範說明](http://ecma262-5.com/ELS5_HTML.htm#Section_15.4.4.11):*「執行與[[Get]],[[Put]]的實現相關的調用序列,和[[Delete]]內部方法的'obj'「*我假設'NodeList's沒有這些內部方法......但我可能是錯的。無論如何,它確實以這種方式工作。 –

2

我排序的HTMLCollection的建議是:

window.onload = function() { 
 
    var parentNode = document.getElementById('test-list'); 
 
    var e = document.getElementById('test-list').children; 
 
    [].slice.call(e).sort(function(a, b) { 
 
    return a.textContent > b.textContent; 
 
    }).forEach(function(val, index) { 
 
    parentNode.appendChild(val); 
 
    }); 
 
}
<ol id="test-list"> 
 
    <li class="lang">Scheme</li> 
 
    <li class="lang">JavaScript</li> 
 
    <li class="lang">Python</li> 
 
    <li class="lang">Ruby</li> 
 
    <li class="lang">Haskell</li> 
 
</ol>

+1

如果像我這樣的人想知道,沒有必要調用val.remove(),因爲appendChild()會自動執行。 –

0

我糾正gaetanoM的代碼,這一個工程與IE:

window.onload = function() { 
 
    var parentNode = document.getElementById('test-list'); 
 
    var e = document.getElementById('test-list').children; 
 
    [].slice.call(e).sort(function(a, b) { 
 
    \t if (a.textContent > b.textContent) return 1; 
 
    if (a.textContent < b.textContent) return -1; 
 
    return 0; 
 
    }).forEach(function(val) { 
 
    parentNode.appendChild(val); 
 
    }); 
 
}
<ol id="test-list"> 
 
    <li class="lang">Scheme</li> 
 
    <li class="lang">JavaScript</li> 
 
    <li class="lang">Python</li> 
 
    <li class="lang">Ruby</li> 
 
    <li class="lang">Haskell</li> 
 
    <li class="lang">Tata</li> 
 
    <li class="lang">Aaaaa</li> 
 
    <li class="lang">Drue</li> 
 
</ol>