【前端基础】动态脚本与JSONP
博主入职两个月了,越来越感受到打好基础对于前端工程师的重要性,在向着狂拽酷炫的框架&构建工具狂飚之前,必须有一个坚实的基础打底,才不至于轻易翻车。所以博主最近一直在恶补《JS高级程序设计》,发现了很多第一次读时忽略的、有趣的地方。不愧是经典,常读常新呀!
PART 1 最熟悉的陌生人——动态脚本
对于一些刚接触前端不久的同学来说,“动态脚本”可能是一个有些陌生的字眼,我也是偶然看高程,才想起同桌的你……不,才注意到这个技术。但事实上,这是每个前端每天都会用到的技术,也是从jQuery到各种狂拽酷炫的前端框架得以运行的基础技术。那它到底是谁呢?
来看一行代码:
<script src="jquery.js"></script>
眼熟吧?
写过吧?
恭喜你,你已经是会使用动态脚本技术的前端攻城狮了!
……纳尼?
没错!不要觉得这行代码司空见惯,其实仔细研究下,还颇有点因缺斯艇呢~
记住一点,网页归根到底就是一个HTML页面,除此之外别无他物。其他如JS、CSS、图片等,都是页面上的资源,从属于这个页面。JS代码只有作为script类型的DOM节点的内部文本的形式被添加到网页上,在浏览器解析DOM结构解析到script节点时,才会被执行。动态脚本,顾名思义,是“动态”的JS代码——“动态”的意思是,不是预先写在HTML页面上的,而是在页面解析的过程中被添加上去的。
动态添加脚本有两种方法:一是DOM操作,像插入其他类型的DOM节点一样插入一个script节点到页面,其内部的JS代码会被立即执行;二是如jQuery那个例子所示,从某个路径加载js文件到页面上来,可以理解为文件中的代码被复制粘贴到这个script标签中了,这些代码会在加载完成后被执行。
举个栗子:
<!-- 出于简略,只写body的代码 -->
<body>
<!-- 静态脚本 -->
<script>
console.log(1);
var scriptDOM = document.createElement('script');
scriptDOM.innerHTML = 'console.log(2);'; // 动态脚本的内容
document.body.appendChild(scriptDOM); // 动态插入script DOM节点
console.log(3);
</script>
</body>
这个页面上有一段静态脚本,其在执行时会向body插入一个script子节点。用浏览器打开这个页面,console会顺序打印出“1 2 3”这三个数字。查看页面,变成了这样:
<!-- 出于简略,只写body的代码 -->
<body>
<!-- 静态脚本 -->
<script>
console.log(1);
var scriptDOM = document.createElement('script');
scriptDOM.innerHTML = 'console.log(2);'; // 动态脚本的内容
document.body.appendChild(scriptDOM); // 动态插入script DOM节点
console.log(3);
</script>
<!-- 动态插入的的脚本 -->
<script>console.log(2);</script>
</body>
这个最终页面有趣的地方在于,包裹“console.log(2);”的script标签明明排在原来的标签的后面,但2却比3先打印出来。事实上,往任何地方插入动态脚本,其中的代码都会在插入后立刻执行。通过src属性引入的JS代码也是如此,一旦加载完成就立刻执行。
这是脚本语言灵活性的绝佳体现呀!想想编译型语言如C++、Java,所有代码必须预先编译好才能执行,无法做到像JS这样,不用编译不说,还可以在原本的代码执行到一半时,忽然插进来一堆新代码并且立即得到执行;就好比原本宴会邀请到了99个宾客,饭吃到一半,忽然来了个不速之客,还是个自来熟,坐下就开始与众人谈笑风生、觥筹交错,于是东道主JavaScript顺手就把宾客人数改成了100,毫无违和感;若是换成C++或Java做东,只会在宴会开始后把所有入口全部封死,不再允许任何人进入。
PART 2 动态脚本的应用:JSONP
“跨域”是前端面试中几乎必考的问题,而JSONP是一个比较简单好使的解决方案。
JSONP诞生的背景是,“跨域”只是AJAX所受的安全策略限制,只要域名、协议、端口这3项有1项不一致,浏览器就禁止发送AJAX请求。而像<script><img><link>这类标签的src属性不受此限,可以填写任意域名的地址(想想jQuery的CDN地址,还有一堆图床网站……)。于是聪明的前端攻城狮们想到了利用动态脚本来获取json数据的套路,名曰JSON Padding,意思是“JSON填充”。
那具体怎么个做法呢?分三步
步骤1
让服务器端略改下代码:当一个get请求的查询参数里有callback一项时,譬如一个URL长这样:
http://someurl.com/data?callback=handler
那么服务器就不要直接把JSON文件作为响应内容了,而是返回一个动态生成的JS文件,其中的代码是
handler({JSON数据});
其实就是一个handler函数的调用,同时把JSON作为参数“填充”进去。
步骤2
回到前端。定义好负责处理JSON数据的handler函数:
function handler(json) {
// 处理json数据
}
步骤3
在需要跨域获取数据时,向页面插入一个script DOM元素:
var script= document.createElement('script');
script.src = 'http://someurl.com/data?callback=handler';
document.body.appendChild(script);
这个script元素的src属性值带有一个callback查询参数,于是服务器会返回步骤1中的代码,这段代码被下载完成后立刻执行,handler恰好是已经定义好的函数,而梦寐以求的跨域JSON数据就这样作为handler的实参被传到了当前页面上!
最后是两点注意事项:
1. 用这种方法可以请求任何类型的数据,不限制为JSON,只是因为JSON最常用,所以命名为JSONP。
2. JSONP是为了帮AJAX绕开跨域限制而使用的一种技巧,它本身跟AJAX没有半毛钱关系,在不支持AJAX的浏览器上照样可以用JSONP技术。
【前端基础】动态脚本与JSONP的更多相关文章
- 前端基础面试题(JS部分)
1.几种基本数据类型?复杂数据类型?值类型和引用数据类型?堆栈数据结构? 基本数据类型:Undefined.Null.Boolean.Number.String 值类型:数值.布尔值.null.und ...
- BAT 前端开发面经 —— 吐血总结 前端相关片段整理——持续更新 前端基础精简总结 Web Storage You don't know js
BAT 前端开发面经 —— 吐血总结 目录 1. Tencent 2. 阿里 3. 百度 更好阅读,请移步这里 聊之前 最近暑期实习招聘已经开始,个人目前参加了阿里的内推及腾讯和百度的实习生招聘, ...
- 前端基础面试题(js部分)
前端基础面试题(JS部分) 1.几种基本数据类型?复杂数据类型?值类型和引用数据类型?堆栈数据结构? 基本数据类型:Undefined.Null.Boolean.Number.String值类 ...
- web前端基础知识及快速入门指南
web前端基础知识及快速入门指南 做前端开发有几个月了,虽然说是几个月,但是中间断断续续的上课.考试以及其它杂七杂八的事情,到现在居然一直感觉自己虽然很多前端的知识很眼熟,却也感觉自己貌似也知识在门口 ...
- web前端基础学习路线
1.HTML和CSS的基础知识,完成网页的初步设计 2.JavaScript基础知识和DOM.BOM的学习 3.前端基础框架:CSS框架Bootstrap.JavaScript框架jquery的熟悉使 ...
- JS BOM DOM对象 select联动 计时器 时间 css操作 节点(标签 ) 查找标签 {前端基础之BOM和DOM}
前端基础之BOM和DOM 前戏 到目前为止,我们已经学过了JavaScript的一些简单的语法.但是这些简单的语法,并没有和浏览器有任何交互. 也就是我们还不能制作一些我们经常看到的网页的一些交互,我 ...
- 前端基础之BOM和DOM day52
前端基础之BOM和DOM 前戏 到目前为止,我们已经学过了JavaScript的一些简单的语法.但是这些简单的语法,并没有和浏览器有任何交互. 也就是我们还不能制作一些我们经常看到的网页的一些交互 ...
- 前端基础之JavaScript day51
前端基础之JavaScript JavaScript概述 JavaScript的历史 1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中) ...
- 浏览器环境下JavaScript脚本加载与执行探析之动态脚本与Ajax脚本注入
在<浏览器环境下JavaScript脚本加载与执行探析之defer与async特性>中,我们研究了延迟脚本(defer)和异步脚本(async)的执行时机.浏览器支持情况.浏览器bug以及 ...
随机推荐
- 内核对象kobject和sysfs(3)——kobj分析
内核对象kobject和sysfs(3)--kobj分析 在分析kobj之前,先总结下kobj的功能: 实现结构的动态管理: 实现内核对象到sysfs的映射: 实现自定义属性的管理. 关注一下kobj ...
- 双向循环链表(C语言描述)(二)
链表的基本操作基于对链表的遍历:计算链表的长度就是对链表进行一次遍历: int linkedlist_length(const LinkedList list) { assert(list); ; L ...
- 【mock.js】后端不来过夜半,闲敲mock落灯花 ——南宋·赵师秀
mock的由来[假] 赵师秀:南宋时期的一位前端工程师 诗词背景:在一个梅雨纷纷的夜晚,正值产品上线的紧张时期,书童却带来消息:写后端的李秀才在几个时辰前就赶往临安度假去了, 赵师秀非常生气 ...
- proxifier配合ss,实现全局代理
proxfixer配合ss的话,基本可以实现全局代理,分应用代理,或者玩外服的游戏(一般的游戏默认不走代理,本软件可以强制应用代理) 由于ss使用的是sockets5代理,一般情况下只有浏览 ...
- 多系统重装其中Win7后的启动引导列表恢复
重装Win7后会导致原grub引导被覆盖,要修复grub需要一张Ubuntu的LiveCD(安装光盘),用LiveCD启动电脑,进入Try Ubuntu(试用Ubuntu),进入之后打开终端,做如下几 ...
- mysql获取当前时间,前一天,后一天
负责的项目中,使用的是mysql数据库,页面上要显示当天所注册人数的数量,获取当前的年月日,我使用的是 CURDATE(), 错误的sql语句 eg:SELECT COUNT(*) FROM USER ...
- CentOS6 安装Sendmail + Dovecot + Squirrelmail
本文记录在本地虚拟机CentOS6上搭建Sendmail + Dovecot + Squirrelmail 的Webmail环境的过程,仅仅是本地局域网的环境测试,不配置DNS, 也没有安全认证,Sq ...
- [stm32F429-DISCO-HAL] 1.先说说关于stm32Cube的一些事情。然后,Start with it...
目前,我觉得STM32CUBE最大的方便在于,可以使用STM32CubeMX软件来图形化配置外设.首先贴出官网的PDF,Getting started with STM32CubeF4 firmwar ...
- web前端+javascript+h5电子书籍和实战分享
有很多前端伙伴们学习前端很多了,但是如何能成为优秀的程序员呢,前端必学的知识点相信学习前端的伙伴们心里都非常清楚.主要的三要素包括HTML.CSS和JavaScript.那么学好JavaScript是 ...
- HDU 1028 Ignatius and the Princess III:dp or 母函数
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1028 题意: 给你一个正整数n,将n拆分成若干个正整数之和,问你有多少种方案. 注:"4 = ...