Reference and array clone

本文探讨了使用JavaScript构建树形结构HTML,并为每个节点存储路径的问题。文章详细介绍了递归构建树形结构的方法,以及如何正确处理路径数组的引用问题,确保每个节点拥有正确的路径数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

In JavaScript, object and array are passed by reference.

Sometimes you may come into trouble if you don’t keep this in mind, especial in
recursion.

Let’s see an example:

First, prepare a JavaScript array to present a tree data:

    var treeData = [{ "name": "root1",
        "kids": [{ "name": "leaf1" }, { "name": "leaf2"}] },
        { "name": "root2"}];

The expected html structure is:

    <ul>
        <li>root1
            <ul>
                <li>leaf1</li>
                <li>leaf2</li>
            </ul>
        </li>
        <li>root2</li>
    </ul>

Our JavaScript code:

    function resolveTree(rootNode, kids) {
        var ulNode = $("<ul />").appendTo(rootNode);
        $.each(kids, function(i, item) {
            var liNode = $("<li />").html(item.name).appendTo(ulNode);
            if (item.kids) {
                resolveTree(liNode, item.kids);
            }
        });
    } 

    resolveTree($("#tree"), treeData);

Next, we want to store the tree node’s path.

For example, leaf1 - [root1, leaf1], leaf2 - [root1, leaf2], root2 - [root2]

We modifiy the resolveTree function:

    function resolveTree(rootNode, kids, path) {
        var ulNode = $("<ul />").appendTo(rootNode);
        $.each(kids, function(i, item) {
            var liNode = $("<li />").html(item.name).appendTo(ulNode);
            path.push(item.name);
            liNode.data("path", path).click(function(event) {
                event.stopPropagation();
                alert($(this).data("path"));
            });
            if (item.kids) {
                resolveTree(liNode, item.kids, path);
            }
            path.pop();
        });
    }
    resolveTree($("#tree"), treeData, []);

The logic must be right, but the result is suprising.

No matter which node i click, the alert box contains an empty string.

What’s the matter?

oh… the array is passed by reference….

The variable path in the code - liNode.data(”path”, path) - is a reference. Then
we want a clone of the array.

There are many method to create a array clone.

    // Method 1
    var newArray = [];
    for (var i = 0; i < oldArray.length; i++) {
        newArray.push(oldArray[i]);
    } 

    // Method 2
    var newArray = oldArray.slice(0); 

    // Method 3
    var newArray = [].concat(oldArray);

The final solution:

    $(function() { 

        var treeData = [{ "name": "root1", "kids": [{ "name": "leaf1" }, { "name": "leaf2"}] }, { "name": "root2"}]; 

        function resolveTree(rootNode, kids, path) {
            var ulNode = $("<ul />").appendTo(rootNode);
            $.each(kids, function(i, item) {
                var liNode = $("<li />").html(item.name).appendTo(ulNode);
                path.push(item.name);
                liNode.data("path", [].concat(path)).click(function(event) {
                    event.stopPropagation();
                    alert($(this).data("path"));
                });
                if (item.kids) {
                    resolveTree(liNode, item.kids, path);
                }
                path.pop();
            });
        } 

        resolveTree($("#tree"), treeData, []);
    });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值