Javascript 多个键名,相同的对值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14743536/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Multiple key names, same pair value
提问by SomeShinyObject
I'm trying to setup an object literal in a JavaScript script that has a key with multiple names. referring to the same object value i.e. something like these that I have already tried:
我正在尝试在具有多个名称的键的 JavaScript 脚本中设置对象文字。指的是相同的对象值,即我已经尝试过的类似的东西:
var holidays: {
"thanksgiving day", "thanksgiving", "t-day": {
someValue : "foo"
}
}
var holidays: {
["thanksgiving day", "thanksgiving", "t-day"]: {
someValue : "foo"
}
}
Is there a way I can accomplish this?
有没有办法我可以做到这一点?
采纳答案by Artem Sobolev
Another approach is to do some postprocessing
另一种方法是做一些后处理
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"
}
});
回答by Scott Sauyet
JSON does not offer such a feature, nor do Javascript object literals.
JSON 不提供这样的功能,Javascript 对象字面量也不提供。
You might be able to make do with something like this:
你也许可以做这样的事情:
holidays = {
thanksgiving: {foo: 'foo'},
groundhogDay: {foo: 'bar'},
aliases: {
'thanksgiving day': 'thanksgiving',
't-day': 'thanksgiving',
'Bill Murrays nightmare': 'groundhogDay'
}
}
and then you can check
然后你可以检查
holidays[name] || holidays[holidays.aliases[name]]
for your data.
为您的数据。
It's not a wonderful solution. But it wouldn't be too difficult to write a little function that created this sort of object out of a representation like:
这不是一个很好的解决方案。但是编写一个小函数来创建这种对象的表示形式并不太难,例如:
[
{
names: ['thanksgiving', 'thanksgiving day', 't-day'],
obj: {foo: 'foo'}
},
{
names: ['groundhogDay', 'Bill Murrays nightmare'],
obj: {foo: 'bar'}
},
]
if that would be easier to maintain.
如果那会更容易维护。
回答by Joseph Merdrignac
Another solution, if you can afford RegExp execution, and ES6 Proxy:
另一个解决方案,如果你能负担得起 RegExp 执行和 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
See docs:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/get
请参阅文档:https:
//developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/get
回答by elclanrs
I guess you could do something like this:
我想你可以做这样的事情:
var holidays = {
'thanksgiving day': {
foo: 'foo'
}
};
holidays.thanksgiving = holidays['t-day'] = holidays['thanksgiving day'];
If you see yourself doing this often or you have more values consider this pattern:
如果您发现自己经常这样做,或者您有更多的价值观,请考虑以下模式:
'thanksgiving, t-day, thanks, thank, thank u'.split(',').forEach(function(key) {
holidays[key] = holidays['thanksgiving day'];
});
A better approach would be to process your data beforehand instead of adding duplicates.
更好的方法是事先处理您的数据,而不是添加重复项。
回答by shaedrich
That should work as expected:
这应该按预期工作:
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;
}
回答by Joseph Merdrignac
Same reponse (ES6 Proxy, RegExp), but in a shorter way (and significantly less legible)
相同的响应(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
回答by Malvineous
With ES6 you could do it like this, but it's not ideal:
使用 ES6,您可以这样做,但这并不理想:
const holidays = {
"single": {
singleValue: "foo",
},
...([
"thanksgiving day", "thanksgiving", "t-day",
].reduce((a, v) => ({...a, [v]: {
someValue: "foo",
}}), {})),
"other": {
otherValue: "foo",
},
};
I still think the cleanest solution is probably:
我仍然认为最干净的解决方案可能是:
let holidays = {
"t-day": {
someValue: "foo",
},
};
holidays["thanksgiving"] = holidays["t-day"];
holidays["thanksgiving day"] = holidays["t-day"];
回答by user3106262
//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");
// ;)
回答by rvighne
Now this may be overkill for you, but here's a generic function that will create an object with "multiple keys." What it actually does is have one real property with the actual value, and then defines getters and setters to forward operations from the virtual keys to the actual property.
现在这对您来说可能有点矫枉过正,但这里有一个通用函数,它将创建一个具有“多个键”的对象。它实际上做的是拥有一个具有实际值的真实属性,然后定义 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);
}
This is less sketchy than you would expect, has basically no performance penalty once the object is created, and behaves nicely with enumeration (for...inloops) and membership testing (inoperator). Here's some example usage:
这比您预期的要粗略,一旦创建对象,基本上没有性能损失,并且在枚举(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
Taken from my Gist, which you may fork.
取自我的 Gist,你可以分叉。

