- /**
- * url: 请求 url
- * callback: 回调函数, 参数如下
- * - status 表示状态, 有 success,error,timeout,abort 四个状态
- * - data 返回的数据
- * opts: 配置选项, 可选
- * - param 查询参数名, 默认为 callback
- * - timeout 超时时间, 默认为 60000, 单位 ms
- */
- function jsonp(url, callback, opts) {
- var id = '__jsonp' + (jsonp.count = jsonp.count || 0, jsonp.count++); // 调用的函数名
- var param = opts.param || 'callback'; // 查询参数名
- var script, cleaned;
- var timer = setTimeout(function () {
- cleanup('timeout');
- }, opts.timeout != null ? opts.timeout : 60000);
- function cleanup(status, data) {
- // 就算把 script 标签移除了, 返回的 js 内容还是会执行, 所以只有 script 的状态最终确定后才能删除 window[id]
- switch (status) {
- case 'success':
- case 'error':
- script.parentNode.removeChild(script);
- delete window[id];
- break;
- }
- if (!cleaned) {
- cleaned = true;
- clearTimeout(timer);
- callback && callback(status, data);
- }
- }
- window[id] = function (data) {
- cleanup('success', data);
- };
- url += (~url.indexOf('?') ? '&' : '?') + param + '=' + encodeURIComponent(id);
- url = url.replace('?&', '?');
- // 创建 script
- script = document.createElement('script');
- script.src = url;
- script.onerror = function () {
- cleanup('error');
- };
- // 不管插到哪个位置, 都是一添加到 dom 上就会立即执行该 script, 且不会重复执行, 即同步执行
- document.getElementsByTagName('script')[0].parentNode.appendChild(script);
- return function () {
- cleanup('abort');
- };
- }
下面不管是插到哪个位置, 都是先 alert ttt, 然后再 alert 222
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- <script>
- var target = document.getElementsByTagName('script')[0];
- var script = document.createElement('script');
- script.textContent = 'alert("ttt")';
- // target.parentNode.insertBefore(script, target);
- target.parentNode.appendChild(script);
- alert('222')
- </script>
- </head>
- <body>
- </body>
- </html>
来源: http://www.qdfuns.com/article/17631/09ac9cf84744025861bc371d9beacbc8.html