可变范围问题

时间:2014-01-26 12:14:26

标签: javascript

请原谅模糊的标题。我不确定是什么导致了这个问题,而且不能更具体。

我有两个连续的函数调用,其中第一个函数是“弄乱”我的第二个函数中的变量。虽然在我看来,所有变量都是其功能的本地变量。

var data = [    
    'Science Fiction',
    'Business / Management',
    'Business / Management / Leadership',
];

function getName(parts) {
    return parts[parts.length - 1];    
}

function getTrail(parts) {
    if (parts.length === 1) return null;
    parts.pop();
    return parts.join(' / ');
}

function getParents(parts) {
    if (parts.length === 1) return null;
    parts.pop();
    return parts;
}

function generate(path) {
    var parts = path.split(' / ');
    return {
        name: getName(parts),        
        trail: getTrail(parts), // <= Problem?
        parents: getParents(parts) // <= Last part is missing when getTrail(parts) is called before.
    };
}

var categories = data.map(generate);

请参阅 http://jsfiddle.net/n6Dud/ ,了解更好的间隔和工作示例。

运行示例时,您可以检查控制台并查看object.parents中的最后一部分是否丢失。我怀疑来自parts.pop()的{​​{1}}。

为什么会这样,我该如何解决呢?

3 个答案:

答案 0 :(得分:1)

getTrail弹出parts的最后一个元素,因为parts是对原始数据的引用,即使在函数返回后,更改也是可见的。

您需要通过操作parts的副本来使操作具有非破坏性。这可以使用slice来完成除最后一个元素之外的所有内容的复制:

if (parts.length === 1) return null;
return parts.slice(0, -1).join(' / ');

答案 1 :(得分:0)

当您在JavaScript中传递数组时,您实际上是将引用传递给该数组,而不是它的副本。

因此,对该阵列的任何修改也会修改原件。如果您想确保修改原件,您应该自己复制,例如:

var copy = parts.slice(0);

因为碰巧你不想要副本的最后一个元素,你可以在复制时删除它:

var copy = parts.slice(0, -1);

答案 2 :(得分:0)

要使其工作,您需要克隆对象(这意味着您必须将其所有属性复制到另一个对象)以确保您正在编辑的对象是另一个对象。对象的行为与其他数据类型(如字符串)不同。对于对象,变量保存对象引用,而不保存对象本身。这使得将对象传递给另一个函数,然后在另一个函数中编辑该对象,您还将编辑原始对象。

您可以通过简单的forloop复制对象:

function cloneObj(o) {
    var clone = {};
    for (var i in o) {
        if (typeof o[i] === 'object') clone[i] = cloneObj(o[i]);
        else clone[i] = o[i];
    }
}

或对于数组,使用Alnitak提到的方法:

var copied = parts.slice(0);