2014-01-26 76 views
0

請原諒模糊標題。我不確定是什麼導致了問題,不能更具體。可變範圍問題

我有兩個連續的函數調用,其中第一個函數與第二個函數中的變量「混淆」。儘管在我看來,所有變量都是局部的。

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()getTrail()

這是爲什麼,我該如何解決它?

回答

1

getTrail彈出parts的最後一個元素,並且因爲parts是對原始數據的引用,所以即使在函數返回後,該更改也是可見的。

您需要通過在parts的副本上進行操作來使操作非破壞性。

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

當你傳遞一個數組中的JavaScript你有效地傳遞參考到陣列,而不是它的一個副本:這可以通過使用slice把一切副本,但最後一個元素來完成。

因此對該數組的任何修改都會修改原始數據。如果你想確保你修改你應該把你自己的副本原件,如:

var copy = parts.slice(0); 

由於正好你不想副本的最後一個元素,你可以去除說出來的時候你把副本:

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

感謝參宿一,我不知道這樣跨甚至功能。 –

0

爲了使這項工作,你需要克隆的對象(這意味着你必須在其所有屬性到另一個對象複製),以確保對象你正在編輯是一個不同的對象。對象的行爲與其他數據類型(如字符串)的行爲不同。對於對象,變量保存對象引用,而不是對象本身。這使得將對象傳遞給另一個函數,然後在另一個函數中編輯該對象,您還將編輯原始對象。

你可以做一個簡單的for循環了對象複製:

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]; 
    } 
} 

或陣列,利用參宿一提到的方法:

var copied = parts.slice(0); 
+0

也謝謝你的回答! –