0

简单的说

我有一个由对象组成的树结构。

是否可以构建该树并向每个对象添加对其父对象的引用?

我知道引用适用于对象,但我不确定在这种情况下是否可以?

我希望能够写出这样的东西

currentLevel = this.getParent();

另一个例子是

this.getChildList().addChild({name: test,parent: this}) 

没有副本并从第一个创建多个树。

第二个问题

引用如何与数组一起使用?它们被视为对象还是取决于它们的内容?

第三个问题

通过字符串 JSON 序列化将树保存在浏览器的缓存中会破坏引用吗?

4

3 回答 3

2

好的,所以最有可能的框架在那里,但我写了一个快速的东西,它支持JSON 序列化和反向(通过它自己的方法)。我从尼尔的回答中获得了基本灵感。例子

var a = new MyTreeNode('a'), // make some nodes
    b = new MyTreeNode('b'),
    c = new MyTreeNode('c');

a.addChild(b).addChild(c); // a parent of b parent of c

c.getParent() === b; // true

var str = a.toJSON(); // "{"nodeName":"a","childNodes":[{"nodeName":"b","childNodes":[{"nodeName":"c","childNodes":[]}]}]}"

MyTreeNode.parseJSON(str); // MyTreeNode (same structure as before)

完整代码

/* MyTreeNode(String nodeName)
Instance Properties
 - nodeName,   String
 - childNodes, Array of MyTreeNodes
 - parentNode, MyTreeNode
Instance Methods
 - addChild(MyTreeNode node),    child MyTreeNode
 - removeChild(MyTreeNode node), child MyTreeNode
 - getParent,                    parent MyTreeNode
 - getChildList,                 Array of MyTreeNodes
 - serialise,                    JSON-safe Object
 - toJSON,                       String
Constructor Methods
 - deserialise(Object serialised), MyTreeNode
 - parseJSON(String JSONString),   MyTreeNode
*/
var MyTreeNode = (function () {
    function MyTreeNode(nodeName) {
        nodeName && (this.nodeName = nodeName);
        this.childNodes = [];
    }

    MyTreeNode.prototype.parentNode = null;
    MyTreeNode.prototype.childNodes = [];
    MyTreeNode.prototype.nodeName = '';

    // getters
    MyTreeNode.prototype.getChildList = function () {
        return this.childNodes = [];
    };
    MyTreeNode.prototype.getParent = function () {
        return this.parentNode;
    };

    // add/remove
    MyTreeNode.prototype.removeChild = function (node) {
        var i = this.childNodes.indexOf(node);
        if (node.parentNode !== this || i == -1)
            throw new ReferenceError('node is not a child of this');
        this.childNodes.splice(i, 1);
        node.parentNode = null;
        return node;
    };
    MyTreeNode.prototype.addChild = function (node) {
        if (node.parentNode) node.parentNode.removeChild(node);
        node.parentNode = this;
        this.childNodes.push(node);
        return node;
    };

    // JSON
    MyTreeNode.prototype.serialise = function () {
        var o = {
            nodeName: this.nodeName,
            childNodes: []
        }, i;
        for (i = 0; i < this.childNodes.length; ++i) {
            o.childNodes.push(this.childNodes[i].serialise());
        }
        return o;
    };
    MyTreeNode.prototype.toJSON = function () {
        return JSON.stringify(this.serialise());
    };
    MyTreeNode.deserialise = function (o) {
        var p = new MyTreeNode(o.nodeName), i;
        for (i = 0; i < o.childNodes.length; ++i) {
            p.addChild(MyTreeNode.deserialise(o.childNodes[i]));
        }
        return p;
    };
    MyTreeNode.parseJSON = function (str) {
        var o = JSON.parse(str);
        return MyTreeNode.deserialise(o);
    };
    return MyTreeNode;
}());
于 2013-06-14T15:39:40.140 回答
2

可以通过创建一个“TreeNode”类来做到这一点:

var TreeNode = (function(){

    //keep track of parent node
    TreeNode.prototype.parent = null;
    //keep track of children
    TreeNode.prototype.children = [];

    function TreeNode(parent) {
        if(parent !== undefined) {
            if(this.setParent(parent)) {
                this.parent.addChild(this);
            }
        }
        //...
    }

    TreeNode.prototype.setParent = function(parent) {
        //add some sort of check to make sure it is a `TreeNode`
        if(parent instanceof TreeNode) {
            this.parent = parent;
            return true;
        }
        return false;
    }

    TreeNode.prototype.addChild = function(child) {
        //add some sort of check to make sure it is a `TreeNode`
        if(child instanceof TreeNode) {
            this.children.push(child);
            child.setParent(this);
        }
    }

    TreeNode.prototype.getParent = function(){
        return this.parent;
    }

    TreeNode.prototype.getChildren = function(){
        return this.children;
    }

    return TreeNode;

})();

然后你可以从中扩展。

示例代码:

var node_a = new TreeNode();
var node_b = new TreeNode(node_a);
var node_c = new TreeNode(node_a);

console.log(node_a.getParent(), node_c.get_parent()); //null , node_a        
console.log(node_a.getChildren()); //[node_b, node_c]

这只是一个开始,它需要 waaaaaaaaaay 更多的扩展 :-)

于 2013-06-14T15:06:51.910 回答
1

You could traverse your object and add parent properties to every subobject:

function addParents(obj) {
    var name;
    for (name in obj) {
        if (typeof obj[name] === "object") {
            addParents(obj[name]);
            obj[name].parent = obj;
        }
    }
}

var obj = {
    g: {
        k: [
            {
                r : 1
            },
            {
                r : 1
            }
        ],
        j: {
            h: 1
        }
    }
};

addParents(obj);

console.log(obj.g.parent === obj); //true
console.log(obj.g.k.parent === obj.g); //true
console.log(obj.g.k[1].parent === obj.g.k); //true
console.log(obj.g.j.parent === obj.g); //true

And if you want to add objects later on, you could use something like this:

function addChild(obj, child, name){
    obj[name] = child;
    child.parent = obj;
}

addChild(obj.g, {t:1}, "xy");

console.log(obj.g.xy.parent === obj.g); //true

FIDDLE

于 2013-06-14T15:23:08.397 回答