Альтернативы eval () для нескольких вложенных объектов - PullRequest
5 голосов
/ 25 октября 2011

Я пытаюсь создать общее решение i18n для приложения HTML, в котором я работаю. Я ищу альтернативы использованию 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);
    }
  });
});

Любые советы о том, как получить доступ к свойству "pageTitle" внутри объекта i18n без использования eval ()?Мне нужно сохранить структуру объекта, поэтому изменить его расположение на «плоское» решение невозможно.

Спасибо !!!

Ответы [ 3 ]

6 голосов
/ 25 октября 2011

Вы можете использовать скобочный синтаксис, как намекали другие. Но вам нужно разделить и повторить на .:

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);
}
4 голосов
/ 25 октября 2011

Синтаксис точки (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++]];
}

Вы захотите сделать дополнительную проверку, чтобы убедиться, что все поля были обработаны, нули не встречались и т. Д.

1 голос
/ 25 октября 2011

Вы можете разбить строку по периодам и обойти объект:

var q = i18n;
$.each($(this).attr('data-i18n').split('.'), function(index, key){
  if (q) q = q[key];
});

Демо: http://jsfiddle.net/GsVsr/

...