我正在尝试使用JavaScript构建层次结构(树结构)。为此,我写了一个代表树中节点的Node
类。当我从数据库中检索数据时,所有数据都被正确检索(即:根节点的ParentId
为null,它有3个子节点指向它作为父节点,后代节点设置正确以及...)。但是当我尝试将它们映射到我的JavaScript模型时,根节点的Children
属性最终为undefined
。即使在运行时,当我在控制台中输出Children
属性的内容时,我也不知道它是如何可行的,我可以看到子节点被添加到它中。这是我的代码:
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 :(得分: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
变量引用它的内部数据。