2013-02-07 212 views
9

我想在具有多個名稱的鍵的JavaScript腳本中設置對象字面值。指的是我已經嘗試對同一對象的值,即像這些東西:多個鍵名稱,相同的值對

var holidays: { 
    "thanksgiving day", "thanksgiving", "t-day": { 
     someValue : "foo" 
    } 
} 

var holidays: { 
    ["thanksgiving day", "thanksgiving", "t-day"]: { 
     someValue : "foo" 
    } 
} 

有沒有一種方法可以讓我做到這一點?

+0

這不是JSON,它只是一個Javascript對象。 – Barmar

回答

7

另一種方法是做一些後處理

function expand(obj) { 
    var keys = Object.keys(obj); 
    for (var i = 0; i < keys.length; ++i) { 
     var key = keys[i], 
      subkeys = key.split(/,\s?/), 
      target = obj[key]; 
     delete obj[key]; 
     subkeys.forEach(function(key) { obj[key] = target; }) 
    } 
    return obj; 
} 

var holidays = expand({ 
    "thanksgiving day, thanksgiving, t-day": { 
     someValue : "foo" 
    } 
}); 
+0

這比我的建議更好。只要你的數據不包括逗號,我會去這個答案。 –

+0

爲什麼要混合使用for循環和forEach?我會發現它堅持一種風格,可能是'forEach'。 –

+0

@ScottSauyet,你是​​對的。首先,我使用'for',因爲我知道它的身體不會那麼小,而當我遍歷子鍵時,我只執行一條語句,所以我懶得寫'for(var blah ...'。沒有理由混合使用這兩種樣式,當然, –

3

我想你可以做這樣的事情:如果你看到自己經常這樣做,或者你有更多的價值考慮這種模式

var holidays = { 
    'thanksgiving day': { 
    foo: 'foo' 
    } 
}; 

holidays.thanksgiving = holidays['t-day'] = holidays['thanksgiving day']; 

'thanksgiving, t-day, thanks, thank, thank u'.split(',').forEach(function(key) { 
    holidays[key] = holidays['thanksgiving day']; 
}); 

一個更好的辦法是處理您的數據事先,而不是添加重複。

+0

如果有人對此如何工作感到好奇:在JavaScript中,對象通過引用存儲(而字面數字和字符串,只能被複制)。在這裏,通過將* reference *存儲到包含該值的對象,當以任何方式更改該值時,所有其他屬性都可以使用相同的引用訪問新值。 – rvighne

6

JSON不提供這樣的功能,也不提供Javascript對象文字。

您也許能湊合着這樣的事:

holidays = { 
    thanksgiving: {foo: 'foo'}, 
    groundhogDay: {foo: 'bar'}, 
    aliases: { 
     'thanksgiving day': 'thanksgiving', 
     't-day': 'thanksgiving', 
     'Bill Murrays nightmare': 'groundhogDay' 
    } 
} 

,然後你可以檢查

holidays[name] || holidays[holidays.aliases[name]] 

爲您的數據。

這不是一個好的解決方案。但它不會是太難寫創建這類對象的出樣的表現的小功能:

[ 
    { 
     names: ['thanksgiving', 'thanksgiving day', 't-day'], 
     obj: {foo: 'foo'} 
    }, 
    { 
     names: ['groundhogDay', 'Bill Murrays nightmare'], 
     obj: {foo: 'bar'} 
    }, 
] 

,如果這樣做更容易維護。

0

我有這個問題,這是我想出了

function objectDive(parent, str){ 
    if(typeof str === 'object'){ 
    if(str.length){ 
     var str0 = str.shift(); 
     return objectDive(parent[str0], str); 
    }else{ 
     return parent; 
    } 
    }else{ 
    if(typeof str === 'string'){ 
     return objectDive(parent,str.split('.')); 
    } 
    } 
} 
0

現在,這可能會矯枉過正你,但這裏有一個泛型函數這將創建一個「多個鍵」的對象。它實際上做的是擁有一個具有實際值的真實屬性,然後定義getter和setter將操作從虛擬鍵轉發到實際屬性。

function multiKey(keyGroups) { 
    let obj = {}; 
    let props = {}; 

    for (let keyGroup of keyGroups) { 
     let masterKey = keyGroup[0]; 
     let prop = { 
      configurable: true, 
      enumerable: false, 

      get() { 
       return obj[masterKey]; 
      }, 

      set(value) { 
       obj[masterKey] = value; 
      } 
     }; 

     obj[masterKey] = undefined; 
     for (let i = 1; i < keyGroup.length; ++i) { 
      if (keyGroup.hasOwnProperty(i)) { 
       props[keyGroup[i]] = prop; 
      } 
     } 
    } 

    return Object.defineProperties(obj, props); 
} 

這比你所期望的少粗略,已基本一旦對象被創建沒有性能損失,並用枚舉(for...in環路)和成員測試(in操作)很好地表現。以下是一些示例用法:

let test = multiKey([ 
    ['north', 'up'], 
    ['south', 'down'], 
    ['east', 'left'], 
    ['west', 'right'] 
]); 

test.north = 42; 
test.down = 123; 

test.up; // returns 42 
test.south; // returns 123 

let count = 0; 
for (let key in test) { 
    count += 1; 
} 

count === 4; // true; only unique (un-linked) properties are looped over 

取自my Gist,您可能會分叉。

1

這應該按預期工作:

function getItem(_key) { 
    items = [{ 
     item: 'a', 
     keys: ['xyz','foo'] 
    },{ 
     item: 'b', 
     keys: ['xwt','bar'] 
    }]; 

    _filtered = items.filter(function(item) { 
     return item.keys.indexOf(_key) != -1 
    }).map(function(item) { 
     return item.item; 
    }); 
    return !!_filtered.length ? _filtered[0] : false; 
} 
0
//create some objects(!) you want to have aliases for..like tags 
var {learn,image,programming} = 
["learn", "image", "programming"].map(tag=>({toString:()=>tag })); 


//create arbitrary many aliases using a Map 
var alias = new Map(); 
alias.set("photo", image); 
alias.set("pic", image); 
alias.set("learning", learn); 
alias.set("coding", programming); 

//best put the original tagNames in here too.. 
//pretty easy huh? 

// returns the image object 
alias.get("pic"); 

// ;) 
+1

請解釋你的代碼,只有發佈代碼不會幫助OP。 – RaghavGarg

2

另一種解決辦法,如果你能負擔得起正則表達式執行和ES6代理:

let align = new Proxy({ 

    'start|top|left': -1, 
    'middle|center': 0, 
    'end|bottom|right': 1, 

}, { 

    get: function(target, property, receiver) { 

     for (let k in target) 
      if (new RegExp(k).test(property)) 
       return target[k] 

     return null 

    } 

}) 

align.start  // -1 
align.top  // -1 
align.left  // -1 

align.middle // 0 
align.center // 0 

align.end  // 1 
align.bottom // 1 
align.right  // 1 

見文檔:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/get

+0

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/get –

1

相同的響應(ES6代理,RegExp),但在更短(明顯不太清晰)

let align = new Proxy({ 

    'start|top|left': -1, 
    'middle|center': 0, 
    'end|bottom|right': 1, 

}, { get: (t, p) => Object.keys(t).reduce((r, v) => r !== undefined ? r : (new RegExp(v).test(p) ? t[v] : undefined), undefined) }) 

align.start  // -1 
align.top  // -1 
align.left  // -1 

align.middle // 0 
align.center // 0 

align.end  // 1 
align.bottom // 1 
align.right  // 1 
相關問題