Как вызвать функцию javascript из строки JSON?

Если я сделаю сообщение AJAX с jQuery, которое выглядит как

 $.post('MyApp/GetPostResult.json', function(data) {
    // what goes here?
 });

и результат выглядит так

{
    "HasCallback": true,
    "Callback": "function(){ alert('I came from the server'); }"
};

Тогда как мне вызвать функцию обратного вызова? Могу я просто написать if(data.HasCallback){data.Callback();} ?


person smartcaveman    schedule 31.03.2011    source источник


Ответы (4)


Это должно работать:

function(data) {
  if(data.HasCallback) {
    eval(data.Callback);
  }
}

Редактировать: Не смотрел достаточно внимательно. Если вы действительно получаете текст function() { ... }, вам нужно eval(data.Callback + "()").

person Sophie Alpert    schedule 31.03.2011
comment
Что именно делает eval и где я могу найти эту документацию? - person smartcaveman; 31.03.2011
comment
@SLaks, спасибо. Не используйте eval! В разделе говорится, что eval представляет собой угрозу безопасности. Вы случайно не знаете какой-либо хорошей документации/ресурсов о том, когда применима эта проблема? - person smartcaveman; 31.03.2011
comment
Если вы не можете доверять источнику функционального текста, возникает угроза безопасности, что делает вас уязвимым для XSS. . Если вы просто получаете JS со своего сервера, риска нет. - person Sophie Alpert; 31.03.2011
comment
@Mike, это хороший момент, но, по-видимому, если я делаю клиентский вызов серверной функции, я буду знать, как сервер предоставляет ресурс. - person smartcaveman; 31.03.2011
comment
@smartcaveman, Конечно, если вы скажете кому-то не проверять данные из ненадежных источников, тогда они смогут выяснить, что безопасно оценивать, основываясь на своих знаниях о сервере. Но если вы скажете кому-то, что можно безопасно оценивать данные, поступающие с сервера, не зная о сервере сами, то вы оказываете им медвежью услугу. - person Mike Samuel; 31.03.2011

eval("(" + functionDeclarationAsString + ")()");

в то время как functionDeclaractionAsString будет что-то в форме function(){ alert('I came from the server'); }

ИЗМЕНИТЬ

Обозначение (functionReference)(); используется для вызова ссылки на функцию. Следующее будет действительным:

(function() { alert('it works'); })();

Следующее также будет действительным:

var my_function = function(param) { alert(param); };
(my_function)('this is a parameter');
person André Pena    schedule 31.03.2011
comment
Зачем нужны дополнительные скобки и какую роль они играют? - person smartcaveman; 31.03.2011
comment
дополнительные круглые скобки означают, что вы хотите вызвать функцию, объявленную в круглых скобках - person André Pena; 31.03.2011

Лучше хранить код и данные отдельно. Чтобы использовать ваш пример, почему бы не использовать JSON следующим образом:

{
    "Message": "I came from the server"
}

И в вашем JavaScript:

$.post('MyApp/GetPostResult.json', function(data) {
    if (data.Message) {
        alert(data.Message);
    }
});
person jpsimons    schedule 31.03.2011
comment
Потому что я могу максимизировать возможность повторного использования кода и сократить время реализации пользовательского интерфейса, генерируя код на стороне клиента на стороне сервера. - person smartcaveman; 31.03.2011

Вы можете использовать злой eval для выполнения данной строки как кода:

if (data.HasCallback) {
  eval("("+data.Callback+"());");
}

Дополнительные круглые скобки в конце немедленно выполняют вашу функцию.

Задокументировано в злых w3schools

person mVChr    schedule 31.03.2011