Как и все прочее, поначалу работа с JSONP кажется немного загадочной, но стоит только понять принцип действия, и все сразу будет выглядеть очень просто. Чтобы разобраться с этой концепцией, представим, что в странице, загруженной с адреса http://oreilly.com/, динамически создается тег SCRIPT, который добавляется в раздел HEAD. С источником этого тега происходит интересная метаморфоза: он свободно может загружать данные не только из домена oreilly.com, но из любого другого, например из http://example.com?id=23. Реализовать такую операцию на JavaScript достаточно просто:
e = document.createElement("SCRIPT");
e.src="http://example.com?id=23";
e.type="text/javascript";
document.getElementsByTagName("HEAD")[0].appendChild(e);
Обычно тег SCRIPT подразумевает загрузку фактического сценария, но в действительности можно организовать получение любого информационного наполнения, включая и объекты JSON. Однако здесь существует одна проблема – эти объекты можно применять только к разделу HEAD страницы, где невозможно реализовать чтонибудь интересное (разве что испортить внешний вид страницы).
Например, в результате применения этого приема можно получить страницу, как показано ниже, где жирным шрифтом выделен текст, выданный в результате выполнения предыдущего фрагмента JavaScript, который динамически добавляет тег SCRIPT в раздел HEAD:
<html>
<head>
<title>My Page</title>
<script type="text/javascript" >
{foo : "bar"}
</script>
</head>
(body)
Содержимое страницы.
(/body)
</html>
От добавления литерала объекта JavaScript в раздел HEAD мало проку, но представьте, что могло бы произойти, если бы можно было получить данные в формате JSON, содержащие вызов какойнибудь функции, точнее функции, которая уже определена гдето в теле страницы. Это могло бы способствовать достижению удивительных эффектов, потому что в этом случае можно было бы асинхронно запрашивать внешние данные и сразу же передавать их выбранной функции для обработки. Для достижения этого эффекта все, что необходимо, – это вставить тег SCRIPT, возвращающий не просто данные в формате JSON, такие как {foo : "bar"}, а данные, дополненные вызовом функции, например myCallback({foo : "bar"}). Если предположить, что функция myCallback уже определена, то, когда тег SCRIPT завершит загрузку данных, он вызовет функцию, которой передаст данные в виде параметра, фактически воспользовавшись ею как функцией обратного вызова. (Если что то осталось непонятным, стоит задержаться немного и представить себе, как происходит весь этот процесс.)
Но здесь остается еще одна маленькая проблема: как получить объект JSON, содержащий дополнение в виде вызова функции? Довольно просто: добрые дяди из example.com должны предоставить вам возможность указывать дополнительный параметр в строке запроса, позволяющий вам определять имя функции, вызов которой должен быть обернут в объект JSON. Допустим, что в соответствии с их решением, чтобы вызвать свою функцию, вы должны предоставить в строке запроса дополнительный параметр c (в котором указать имя своей функции); тогда обращение по адресу http://example.com?id=23&c=myCallback должно вернуть myCallback({foo : "bar"}). И это все, что требовалось сделать.