Javascript: Как изменить параметры вызова функции на лету? - PullRequest
2 голосов
/ 18 июля 2011

Я получаю некоторый контент 'body' из json-запроса jquery, где я могу получить уникальный элемент javascript, возвращаемый командой:

script_element = $(data.body)[1]

Это равно:

<script type=​"text/​javascript">​
    updater('foo', 'bar', {}, '0', constant='');
</script>​

Итак, typeof script_element возвращает "object"

И, если я запускаю script_element.innerText, я могу получить:

updater('foo', 'bar', {}, '0', constant='');

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

Я пытаюсь изменить thirdпараметр вызова, в данном случае {}, который может меняться в зависимости от возврата вызова json, поэтому я не могу просто найти {}.

Я мог бы также сделать script_element.text.split(',')[2]например, и изменить этот текст на лету, но я подумал, что должен быть лучший способ сделать это.

Я не знаю, сможет ли javascript распознавать и обрабатывать «будущий вызов метода», но все же думаю, что должен быть лучший способ.

Есть идеи?

Ответы [ 4 ]

5 голосов
/ 18 июля 2011

То, что вы могли бы сделать, это скрыть функцию, чтобы иметь возможность изменить третий аргумент.Вы должны определить эту функцию теневого копирования перед извлечением JSON.

var originalUpdater = updater; // keep old function to call

// overwrite (shadowing)
updater = function(a, b, c, d, e) {
    // change c appropriately here
    originalUpdater(a, b, c, d, e);
}

Тогда вы все равно можете просто eval это (что не очень безопасно, но это не ваша точка зрения, если я не ошибаюсь),и он вызовет функцию тени.


Более общий метод теневого копирования будет выглядеть следующим образом:

var originalUpdater = updater; // keep old function to call

// overwrite (shadowing)
updater = function() {
    // change arguments[2] appropriately here
    originalUpdater.apply(this, arguments);
}

Fiddle: http://jsfiddle.net/n7dLX/

3 голосов
/ 18 июля 2011

Сменить сервер.Вместо возврата

<script type=​"text/​javascript">​
    updater('foo', 'bar', {}, '0', constant='');
</script>​

Возврат

{
  "method": "updater",
  "params": [
    "foo", "bar", {}, "0", ''
  ]
}
2 голосов
/ 18 июля 2011

Предполагая, что вы не можете изменить то, что отправляется с сервера, вы можете просто запустить innerText с регулярным выражением и пройти обновление HTML, прежде чем вставить его.

var replacer = /\w+\(([^()]+)\)/gi;
script_element.innerText.replace(replacer, function(matched_text, func_params){
    var orig_func_params = func_params;
    // Make changes to func_params here.
    return matched_text.replace(orig_func_params, func_params);
});

Это можно сделать, выполнив следующие действия:

var replacer = /\w+\(([^()]+)\)/gi;
function replace_arg(script_element, arg_index, replacement_value) {
    script_element.innerHTML = script_element.innerHTML.replace(replacer, 
    function(matched_text, func_params){
        var orig_func_params = func_params;
        func_params = func_params.split(",");
        if (arg_index >= func_params.length) {
             throw new RangeError(arg_index + " is out of range. Total args in function:" + func_params.length);
        }
        func_params[arg_index] = JSON.stringify(replacement_value);
        return matched_text.replace(orig_func_params, func_params.join(","));
    });
return script_element;
}

Это можно назвать так:

script_element = replace_arg(script_element, 3, {"new":"arg"});
0 голосов
/ 18 июля 2011

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

function add(params) {
    var a = params.hasOwnProperty("paramA") ? params.paramA : 0;
    var b = params.hasOwnProperty("paramB") ? params.paramB : 0;
    return a + b;
}

add({paramA: 1, paramB: 2});

В этом случае вы должны использовать hasOwnProperty, чтобы проверить, передана ли функции параметр, который вы ищете, прежде чем пытаться получить к нему доступ.

...