在向其添加项目后,数组被重置为未定义

时间:2013-02-28 07:13:23

标签: javascript data-structures recursion tree

我正在尝试使用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

1 个答案:

答案 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变量引用它的内部数据。