2013-02-28 55 views
1

我想構建一個使用JavaScript的層次結構(樹結構)。爲此,我寫了一個表示樹中節點的類Node。當我從數據庫中檢索數據時,它們都被正確地檢索到(即:根節點的空值爲ParentId,它有3個子節點指向它作爲父節點,並且後代節點的設置也正確。 )。但是當我嘗試將它們映射到我的JavaScript模型時,根節點的Children屬性結束爲undefined。我不知道即使在運行時,如何輸出控制檯中的Children屬性的內容,我可以看到添加到它的子節點。這裏是我的代碼:將項目添加到它後重置爲undefined

var Node = function (obj) { 
    var self = this; 
    var isDefined = obj != undefined; 

    self.hasChildren = function() { 
     return self.Children.length > 0; 
    }; 

    self.hasParent = function() { 
     var p = self.ParentId; 
     return !(p == null || p == undefined || p == 0); 
    }; 

    self.addChildren = function (objArray) { 
     if (!$.isArray(self.Children)) { 
      self.Children = []; 
     } 
     for (var i = 0; i < objArray.length; i++) { 
      self.addChild(objArray[i]); 
     } 
    }; 

    self.addChild = function (obj) { 
     if (obj instanceof Node) { 
      self.Children.push(obj); 
     } else { 
      var n = new Node(obj); 
      self.Children.push(n); 
     } 
    }; 

    self.removeChild = function (n) { 
     var index = self.Children.indexOf(n); 
     if (index > -1) { 
      self.Children.splice(index, 1); 
     } 
    }; 

    self.Id = isDefined ? obj.Id : null; 
    self.ParentId = isDefined ? obj.ParentId : null; 
    self.Name = isDefined ? obj.Name : ''; 
    self.Children = isDefined ? self.addChildren(obj.Children) : []; 
    self.TypeId = isDefined ? obj.TypeId : null; 
}; 

我想到了addChildren法的方式,我會通過來自服務器的原始JSON對象到Node對象的構造函數,然後如果有任何子女(其中基本上具有與父母相同的屬性),則將調用addChildren,這將爲每個元素創建新的Node。最終,該樹將遞歸構建。

那麼我哪裏出錯了?爲什麼Children房產最終成爲undefined

+0

向我們展示您用於創建Node對象的代碼以及調用未定義'.Children'的方法的代碼。 – jfriend00 2013-02-28 07:21:49

+0

@Nucleon,是的,這是意圖。節點的孩子只是它的直接孩子,而不是所有的後代。 – Kassem 2013-02-28 07:33:33

回答

2
self.Children = isDefined ? self.addChildren(obj.Children) : []; 

您正在設置self.Children等於返回self.addChildren()。該功能沒有任何回報。

這裏是一對夫婦的事情,我會建議

function Node(obj) { 
    // clean constructor moving function definitions to prototype 
    var self = this; 

    // ensure that we at least have an object passed in 
    obj = obj || {}; 

    // default values at the top 
    self.Id = null; 
    self.ParentId = null; 
    self.Name = ''; 
    self.Children = []; 
    self.TypeId = null; 

    // fold in data with $.extend, no need to specify each key manually 
    // third object is to overwrite any added Children as those need to be handled seperately 
    $.extend(self, obj, { Children : [] }); 

    // if we have children, add them using the addChildren method 
    if (typeof obj.Children !== undefined && $.isArray(obj.Children)) { 
     self.addChildren(obj.Children); 
    } 
} 

// using prototype to reduce memory footprint 
Node.prototype.hasChildren = function() { 
    return this.Children.length > 0; 
}; 

Node.prototype.hasParent = function() { 
    var p = this.ParentId; 
    return !(p == null || p == undefined || p == 0); 
}; 

Node.prototype.addChildren = function (objArray) { 
    for (var i = 0; i < objArray.length; i++) { 
     this.addChild(objArray[i]); 
    } 
}; 

Node.prototype.addChild = function (obj) { 
    if (obj instanceof Node) { 
     this.Children.push(obj); 
    } else { 
     var n = new Node(obj); 
     this.Children.push(n); 
    } 
}; 

Node.prototype.removeChild = function (n) { 
    var index = this.Children.indexOf(n); 
    if (index > -1) { 
     this.Children.splice(index, 1); 
    } 
}; 

那麼我可以用這個像這樣:

test = new Node({ Id : "Something", Children : [{ Id : "Interior", Children : [] }] }) 

使用原型你減少內存佔用,不創建一個函數引用您創建的每個Node的每個內部功能。每個Node仍然會通過this變量引用它的內部數據。