我有一个JS代码包来处理基本的国际化。
var EN = {
messages: {
newButton: {
text: "New"
},
userSettings: {
language: {
selectYourLanguage: "Choose your preferred language",
fr: "French",
en: "English"
}
}
}
};
var FR = {
messages: {
newButton: {
text: "Nouveau"
},
userSettings: {
language: {
selectYourLanguage: "Choissez votre langage préféré:",
fr: "Français",
en: "Anglais"
}
}
}
};
我想知道是否可以通过"路径"比较2个对象。我希望能够确保没有第一个对象的路径也不在第二个对象中。
我想确保有人为一种语言添加翻译,永远不要忘记将其添加到另一种语言,以便快速失败。
我希望将来能够添加新语言。
有什么想法以优雅和通用的方式来实现这一目标吗?
我正在寻找类似的东西
haveSameKeys(objectList)
其中objectList包含对象(如FR / EN / ...)。订单无关紧要。该列表将保持相对较小的规模。
我倾向于选择返回结果的纯解决方案,而不涉及警告或抛出错误等副作用。
我并不十分关心运行时性能,因为它在开发/集成方面快速失败并且无法在生产中运行。
答案 0 :(得分:1)
<强> jsFiddle Demo
强>
所以你想知道结构是否与另一个对象完全相同?然后每个键将存在于另一个对象中。
我希望能够确保没有第一个对象的路径也不在第二个对象中。
翻译:对象b中的所有路径必须位于对象a中。
function compare(a,b){
//all paths in b must be in a
for(var key in b){
if(a[key] == undefined) return false;
if(toString.call(b[key]) == "[object Array]" || toString.call(b[key]) == "[object Object]"){
if( !compare(a[key],b[key]) ) return false;
}
}
return true;
}
此函数通过对象b递归,并确保对象中的键存在于顶层和每个嵌套层中。如果对象b包含在同一嵌套级别的对象a中不存在的键,则它将返回false。
为了针对对象列表利用该函数,您可以使用嵌套for循环将它们相互比较
function haveSameKeys(objectList){
for(var i = 0; i < objectList.length; i++)
{
for(var n = i+1; n < objectList.length; n++){
if( !(compare(objectList[i],objectList[n]) && compare(objectList[n],objectList[i]) ) ) return false;
}
}
return true;
}
答案 1 :(得分:1)
一个简单的解决方案就是“平坦化”#34;两个对象使用类似于此的函数:
function flatObj(obj, key, res) {
res = res || {};
if(typeof obj != "object" || obj === null) {
res[key] = obj;
return res;
}
return Object.keys(obj).reduce(function(res, k) {
return flatObj(obj[k], (key || "") + "." + k, res);
}, res);
}
var EN = {
messages: {
newButton: {
text: "New"
},
userSettings: {
language: {
selectYourLanguage: "Choose your preferred language",
fr: "French",
en: "English"
}
}
}
};
flat = flatObj(EN)
document.write("<pre>"+JSON.stringify(flat,0,3))
&#13;
然后计算Object.keys(flat(EN))
和Object.keys(flat(FR))
之间的设置差异。
答案 2 :(得分:1)
这是我最终使用的内容。
_xor函数调用需要下划线/ lodash
function getPaths(obj, key, res) {
res = res || {};
if ( typeof obj != "object" || obj === null ) {
res[key] = obj;
return res;
}
return Object.keys(obj).reduce(function(res, k) {
var prefix = key ? key + "." : ""
return getPaths(obj[k], prefix + k, res);
}, res);
}
function getPathsDifferences(objectArray) {
var objectPaths = objectArray.map(function(o) {
return Object.keys(getPaths(o));
});
return _.xor.apply(this,objectPaths);
}
var differences = getPathsDifferences([FR,EN]);
console.debug("differences",differences);
if ( differences.length > 0 ) {
throw new Error("Localization bundles are not consistent on paths: \n" + differences.join("\n"));
}
答案 3 :(得分:0)
使用lodash ...
function compareObjects(firstObject, secondObject) {
var keys = _.keys(firstObject);
for (var i = 0, length = keys.length; i < length; i++) {
var key = keys[i];
if (!secondObject.hasOwnProperty(key)) {
// This is what you don't want
} else if (firstObject[key] instanceof Object) {
compareObjects(firstObject[key], secondObject[key]);
}
}
}