2015-07-11 50 views
0

我在Chrome開發工具中測試以下代碼,即使兩個節點不相同,它也會保持返回true狀態。示例節點如下。只有Div1 & Div4是平等的。我非常自信,我遞歸地觸摸了所有的節點,但是我認爲我沒有用'if'正確設置變量,或者我需要別的地方 - 有點失落,並嘗試了一堆東西。JavaScript遞歸節點等價函數不起作用

var htmlStrings = [ 
    '<div id="one">Some<span>node <em>contents</em> for</span>comparison</div>', 
    '<div id="two">Some<span>node contents for</span>comparison</div>', 
    '<div id="one">Some<span>node <strong>contents</strong> for</span>comparison</div>', 
    '<div id="four">Some<span>node <em>contents</em> for</span>comparison</div>' 
]; 

var div1 = document.createElement('div'); 
div1.innerHTML = htmlStrings[0]; 
document.body.appendChild(div1); 

var div2 = document.createElement('div'); 
div2.innerHTML = htmlStrings[1]; 
document.body.appendChild(div2); 

var div3 = document.createElement('div'); 
div3.innerHTML = htmlStrings[2]; 
document.body.appendChild(div3); 

var div4 = document.createElement('div'); 
div4.innerHTML = htmlStrings[3]; 
document.body.appendChild(div4); 


function nodeEquivalence(node1, node2) { 
    var passed = false; 


     if (node1.nodeType === node2.nodeType) { 
      if ((node1.tagName === node2.tagName || node1.nodeValue === node2.nodeValue)) { 
       passed = true; 
      } 
     } 

     node1 = node1.firstChild; 
     node2 = node2.firstChild; 
     while (node1 && node2) { 
      nodeEquivalence(node1, node2); 
      node1 = node1.nextSibling; 
      node2 = node2.nextSibling; 

     } 

     return passed; 

} 


console.log(nodeEquivalence(div1, div2)); 
console.log(nodeEquivalence(div1, div4)); 
+0

我的猜測是你的「tagName」總是如此,因此它會一直通過。 ||而不是||使用&& –

+0

謝謝。試過,但仍然有同樣的問題。如果它是一個元素,tagName是for;如果它是textNode,nodeValue是for,所以理論上它們都不應該能夠通過。 – devdropper87

回答

0

下面是一個似乎適用於您的測試用例的實現。這使用遞歸來測試子樹。它專門用於處理元素,文檔,文檔片段,文本節點和註釋節點。可以添加對其他類型的節點的支持。

function nodeEquivalence(node1, node2) { 
    var ch1, ch2, nType; 

    // OK to have both node1 and node2 not exist, but only if both are missing 
    if (!node1 || !node2) { 
     return node1 === node2; 
    } 

    // must be same nodeType 
    ntype = node1.nodeType; 
    if (ntype !== node2.nodeType) { 
     return false; 
    } 
    // if there is a tagName, must be same tagName 
    if (node1.tagName && node1.tagName !== node2.tagName) { 
      return false; 
    } 
    switch(ntype) { 
     // nodes that have children 
     case 1: // element node 
     case 9: // document node 
     case 11: // document fragment node 
      // check equivalence on each corresponding child 
      ch1 = node1.firstChild; 
      ch2 = node2.firstChild; 
      while (ch1 && ch2) { 
       if (!nodeEquivalence(ch1, ch2)) { 
        return false; 
       } 
       ch1 = ch1.nextSibling; 
       ch2 = ch2.nextSibling; 
      } 
      return nodeEquivalence(ch1, ch2); 

     // nodes whose content is nodeValue 
     case 3: // text node 
     case 8: // comment node 
      return node1.nodeValue === node2.nodeValue; 

     // other types of nodes 
     default: 
      throw new Error("unsupported type of node"); 
      break; 
    } 
} 

而且,一個工作演示:http://jsfiddle.net/jfriend00/nruL6fdy/


有一些與你的代碼邏輯的問題:

  1. 你試圖使用遞歸調用一個局部變量。這是行不通的。
  2. 一旦發生故障,您並沒有停止比較。
  3. 即使tagName不存在,您的邏輯if (node1.tagName === node2.tagName)也會通過,因此您永遠不會比較nodeValue
  4. 您的while循環會錯過一個節點比另一個節點多的情況。
+0

謝謝!你能否詳細說明#1? – devdropper87

+0

@freezycold - 你在調用'nodeEquivalence(node1,node2);'並期待它做些什麼,但不看它的返回值。 – jfriend00