Передача неизвестного количества переменных с использованием строковой строки и eval, нескольких функций и всех видов - PullRequest
0 голосов
/ 24 марта 2010

Короче говоря, я хочу использовать литерал объекта, чтобы позволить мне передавать неизвестное количество переменных в любом порядке в функцию. Хотя в теории это не имеет большого значения, в моем коде этот литерал объекта передается второй функции с именем on_change.

on_change работает путем сравнения innerHTML элемента со строкой; Если это то же самое, он устанавливает тайм-аут для повторного вызова функции. Если innerHTML элемента отличается от строки, то выполняется третий параметр, это будет либо функция, либо строка. в любом случае это будет выполняться. Я много тестировал эту функцию и использовал ее некоторое время.

Однако я не могу заставить объектный литерал проходить через вызовы функций ...

var params = { xpos:'false'};
on_change('window_3_cont_buffer','','
if(Window_manager.windows[3].window_cont_buffer.getElementsByTagName(\'content\')[0].getElementsByTagName(\'p\')[0].innerHTML == \'ERROR\'){
alert(Window_manager.windows[3].window_cont_buffer.getElementsByTagName(\'content\')[0].getElementsByTagName(\'p\')[1].innerHTML);
return false;
} else { 
Window_manager.windows[3].load_xml(\'location/view.php?location_ID=3\', \'\', ' + params + ' ); }
');

Я называю это частью представления формы. После этой строки я вызываю функцию для загрузки некоторого контента через ajax, который работает нормально и запускает код из функции on_change.

Я протестировал функцию load_xml, она может вызвать alert(param.xpos) и получить правильный ответ. Я даже могу добавить в проверку, что я не определен, так что в остальное время я звоню load_xml Я не завален предупреждениями.

Функция load_xml сначала устанавливает функцию on_change, а затем вызывает функцию для загрузки содержимого в скрытый div. Как только AJAX-запрос обновил этот DIV, функция on_change должна теперь вызывать функцию parse_xml. Это вытаскивает информацию из XML-файла. Однако ... Идея этого буквального параметра объекта заключается в том, что он может указать этой parse_xml функции игнорировать определенные вещи.

on_change("window_" + this.id + "_cont_buffer", "", "Window_manager.windows[" + this.id + "].parse_xml('" + param + "')");

Это часть load_xml, она отлично работает, даже с битом параметра там. за исключением того, что parse_xml не может использовать этот параметр.

Я смог добраться до точки, где parse_xml может alert(param) и дать [object object], что, как я думал, означало, что литерал объекта был пройден, но когда я пытаюсь вызвать alert(param.xpos) Я получаю неопределенный.

Я знаю, что это проблема, и я мог бы обойти ее, просто приняв функцию, принимающую zillion булевы параметры, но это просто не очень хорошее решение.

Ответы [ 4 ]

2 голосов
/ 24 марта 2010

По сути, то, что у вас есть это:

var params = {param: "value"};
foo("bar('one', 'two', 'three');");

... где foo использует eval в этой строке, что-то вроде:

function foo(codestring) {
    eval(codestring);
}

... и вы ищете, как встроить params в это.

Вы могли бы сделать это, сериализовав литерал объекта в виде строки, чтобы при объединении его с другой строкой и оценке всей строки он получал оценку. Браузеры постепенно внедряют сериализацию JSON, но сейчас вы хотите использовать jQuery, Prototype или (если вы просто хотите эту часть) json2.js из Crockford , который предлагает JSON.stringify для поворота объектов, которые можно превратить в строки JSON, в строки JSON. Итак:

var params = {param: "value"};
foo("bar(" + JSON.stringify(params) + ");");

Но то, что вы действительно хотите сделать, - это рефакторинг, так что вся эта логика выражается в виде кода, а не кода в строке. Тогда вы могли бы передать литерал напрямую, плюс целый ряд других преимуществ, включая модульность, отладку и т. Д.

var params = {param: "value"};
function callBar() {
   bar(params);
}
foo(callBar);

... изменение foo таким образом, чтобы оно вызывало функцию, а не eval, содержащее строку. (eval следует избегать всякий раз, когда это возможно, и, перефразируя Далай-ламу, это [почти] всегда возможно.) Мой образец foo меняется на:

function foo(func) {
    func();
}

Если foo необходимо включить дополнительную информацию для bar (и если callBar настроен для обработки этих дополнительных аргументов), он может использовать Function#call или Function#apply, чтобы сделать это. (Эти ссылки относятся к MDC, но не волнуйтесь, они не относятся к Firefox, они были в спецификации ECMA годами и почти повсеместно поддерживаются.)

1 голос
/ 24 марта 2010

Вы не можете поместить объект в строку. Вам придется сериализовать объект, добавить его в строку, а затем проанализировать его обратно в структурированный объект на другой стороне. Простейший способ сделать это - использовать JSON (через JSON.stringify или резервный вариант библиотеки для старых браузеров, у которых его нет), поскольку JSON оценивает как простой JavaScript.

Обратите внимание, что вы не получите обратно тот же объект, но новый с теми же атрибутами и свойствами, и он работает только для простых типов, поэтому вы не можете включить функцию в объект или что-либо еще.

Однако, в любом случае, передача кода JavaScript в строках является анти-паттерном, которого следует избегать. Вместо этого используйте встроенные функции, и вам не нужно беспокоиться о том, что вы можете и не можете поместить в строку, и вы можете избавиться от всего этого нечитабельного переноса и \ -эскапинга:

var params = {xpos: 'false'};
on_change('window_3_cont_buffer', '', function() {
    var w= Window_manager.windows[3];
    var ps= w.window_cont_buffer.getElementsByTagName('content')[0].getElementsByTagName('p');
    if (ps[0].innerHTML==='ERROR') {
        alert(ps[1].innerHTML);
        return false;
    } else { 
        w.load_xml('location/view.php?location_ID=3', '', params);
    }
});
0 голосов
/ 24 марта 2010

Я хочу использовать литерал объекта, чтобы позволить мне передавать произвольное количество переменных в любом порядке в функцию.

Почему бы вам просто не создать объект, содержащий параметры и функции, и передать его? Принимающая функция может просто проверить, установлено ли свойство объекта, прежде чем пытаться его использовать.

0 голосов
/ 24 марта 2010

Некоторые общие приемы, которые могут быть вам полезны:

// Example of calling function objects given as arguments:

function on_change(foo, callback1, callback2) {
    if (foo)
        callback1();
    else
        callback2.call(available_as_this);
}

on_change(foo, function() { your code }, function() { another code });


// Example of function taking arbitrary number of arguments:

function any_params() {
    console.log('I got ' + arguments.length + 'arguments!');
    console.log('First argument: ' + arguments[0]);
}

any_params('one', 'two', 'three', [], null, {});

См. аргументы переменная и call () .

...