2012-02-18 127 views
3

如何通過字符串path.to.obj訪問myobject[path][to][obj]?我想調用一個函數Settings.write('path.to.setting', 'settingValue'),這個函數會寫'settingValue'settingObj[path][to][setting]。我如何在沒有eval()的情況下做到這一點?通過點語法字符串路徑訪問對象

我終於在下面的一個用戶回答它的同時大概找到了它。如果有人感興趣,我會在這裏發佈關於它如何工作的文檔。

(function(){ 
    var o = {}, c = window.Configure = {}; 

    c.write = function(p, d) 
    { 
     // Split the path to an array and assaign the object 
     // to a local variable 
     var ps = p.split('.'), co = o; 

     // Iterate over the paths, skipping the last one 
     for(var i = 0; i < ps.length - 1; i++) 
     { 
      // Grab the next path's value, creating an empty 
      // object if it does not exist 
      co = (co[ps[i]])? co[ps[i]] : co[ps[i]] = {}; 
     } 

     // Assign the value to the object's last path 
     co[ps[ps.length - 1]] = d; 
    } 

    c.read = function(p) 
    { 
     var ps = p.split('.'), co = o; 
     for(var i = 0; i < ps.length; i++) 
     { 
      co = (co[ps[i]])? co[ps[i]] : co[ps[i]] = {}; 
     } 
     return co; 
    } 
})(); 

我有問題的原因是你必須跳過最後一條路。如果包含最後一個路徑,則最終只分配一個任意對象。

回答

3

您可以使用str.split()爲:

path = pathString.split('.'); 
settingObj[path[0]][path[1]][path[2]] = settingValue; 

str.split()將變量分成數組,分裂在您指定的字符的位置。

這只是當然的操作的根源,並假設正確的輸入。

編輯:由於路徑必須是可變長度的,這裏是從語法編輯的更新版本,上面已經證明:

(function(){ 
    var o = {}, c = window.Configure = {}; 

    c.write = function(p, d) 
    { 
     var ps = p.split('.'), co = o; 
     for(var i = 0; i < ps.length - 1; i++) 
     { 
      co = (co[ps[i]])? co[ps[i]] : co[ps[i]] = {}; 
     } 
     co[ps[ps.length-1]] = d; 
    } 

    c.read = function(p) 
    { 
     var ps = p.split('.'), co = o; 
     for(var i = 0; i < ps.length; i++) 
     { 
      co = (co[ps[i]])? co[ps[i]] : co[ps[i]] = {}; 
     } 
     return co; 
    } 

    c.write('path.to.property', 'setting'); 
    alert(c.read('path.to.property')); 
})(); 
+0

但你永遠不知道到底有多少部分路徑。可能是2,可能是6. – LordZardeck 2012-02-18 03:24:59

+0

我的不好,我認爲這是某種預先存在的設置或某事。我把代碼放在一個小提琴裏:http://jsfiddle.net/HVh7X/,我在看到你的編輯之前就開始了,所以我會在一分鐘內更新我的答案。 – Rick 2012-02-18 03:45:00

+0

哈哈,是的,只是想通了。我需要跳過最後一個路徑,因爲我只是分配一個任意值。一旦你編輯你的答案,我會接受它。 – LordZardeck 2012-02-18 03:50:05

2

你的變量co包含處理自己財產的參考,但當您使用co = p更新co的值時,您只覆蓋co的值,而不是該屬性的值。你需要保持到了最後關鍵的參考,並使用該鍵設定值:

http://jsfiddle.net/gilly3/a2p8m/1/

c.write = function(p, d) 
{ 
    var ps = p.split('.'), co = o, key; 
    for(var i = 0; i < ps.length; i++) 
    { 
     if (key) 
     { 
      co = (key in co) ? co[key] : co[key] = {}; 
     } 
     key = ps[i]; 
    } 
    co[key] = d; 
    console.log(co); 
    console.log(o); 
} 

您可能需要使用的key in co而不只是做一個「truthy」檢查。否則,將保留1的值,而0的值將被{}覆蓋。然後再次,這些值中的任何一個都會導致上述代碼的運行時錯誤,因爲您無法將屬性寫入數字。最好的辦法是檢查typeof co[key]

co = co[key] && /object|function/.test(typeof co[key]) ? co[key] : co[key] = {}; 

(我知道我是一個有點晚了我的回答,但把所有的精力與我的拇指打字後,我的身影,我也可能包括也無妨)

我懷疑你遇到分組錯誤。嘗試在三元式移動結束括號到該行的末尾:

co = (co[ps[i]] ? co[ps[i]] : co[ps[i]] = {}); 

我會測試這個自己,但我從我的手機接聽,並與剛剛拇指打字時的jsfiddle是乏味的。