多层嵌套对象中eval()的替代方案

5
我是一名有帮助的助手,以下是您需要翻译的内容:

我正在尝试为我正在开发的HTML应用程序创建一个通用的i18n解决方案。我正在寻找替代方法来使用eval()调用深度嵌套的JavaScript对象:

假设以下是HTML示例:

<div id="page1">
  <h1 data-i18n="html.pageOne.pageTitle"></h1>
</div>

以及它的伴生 Javascript(使用 jQuery):

var i18n;

i18n = {
  html: {
     pageOne: {
       pageTitle: 'Lorem Ipsum!'
     }
  }
};

$(document).ready(function () {
  $('[data-18n]').each(function () {
    var q;

    q = eval('i18n.' + $(this).attr('data-i18n'));
    if (q) {
      $(this).text(q);
    }
  });
});

有没有关于如何在不使用eval()的情况下访问i18n对象中的“pageTitle”属性的建议?我需要保留对象的结构,因此更改其布局为“平面”解决方案是不可行的。
谢谢!
3个回答

6
您可以使用括号语法,正如其他人所示。但是,您需要在“。”处拆分并迭代:
function lookup(obj, path) {
    var keys = path.split('.'),
        result = obj;

    for (var i = 0, l = keys.length; i < l; i++) {
        result = result[keys[i]];

        // exit early if `null` or `undefined`
        if (result == null)
            return result;
    }

    return result;
}

然后:

q = lookup(i18n, $(this).attr('data-i18n'));
if (q) {
  $(this).text(q);
}

干净利落的解决方案。我希望有另一种方式(可能是语言提供的,或者使用jQuery)来完成这个任务。 - Chris R.

4
点语法(object.field)实际上只是object['field']的简写。如果你发现自己正在编写eval('object.'+field),那么你应该简单地写object['field']。在上面的例子中,你可能想要:i18n[$(this).attr('data-i18n')]
由于您的属性采用具有点的方式进行编码,请尝试通过点进行拆分,并遍历字段。例如(这可能可以改进):
var fields = $(this).attr('i18n').split('.');
fieldCount = fields.length;
fieldIdx = 0;
var cur = i18n;
while(cur != undefined && fieldIdx > fieldCount) {
    cur = cur[fields[fieldIdx++]];
}

您需要进行额外的检查以确保所有字段都被处理,没有遇到空值等。


2
我同意括号比eval更好,但在这种情况下不起作用-- {"html.pageOne.pageTitle": ...}{html: {pageOne: {pagetitle: ...}}} - Jonathan Lonowski
哦,我明白了。根据建议更新了答案。 - Jason LeBrun

1
你可以通过句点将字符串分割,并遍历对象:
var q = i18n;
$.each($(this).attr('data-i18n').split('.'), function(index, key){
  if (q) q = q[key];
});

演示:http://jsfiddle.net/GsVsr/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接