博主入职两个月了,越来越感受到打好基础对于前端工程师的重要性,在向着狂拽酷炫的框架&构建工具狂飚之前,必须有一个坚实的基础打底,才不至于轻易翻车。所以博主最近一直在恶补《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的更多相关文章

  1. 前端基础面试题(JS部分)

    1.几种基本数据类型?复杂数据类型?值类型和引用数据类型?堆栈数据结构? 基本数据类型:Undefined.Null.Boolean.Number.String 值类型:数值.布尔值.null.und ...

  2. BAT 前端开发面经 —— 吐血总结 前端相关片段整理——持续更新 前端基础精简总结 Web Storage You don't know js

    BAT 前端开发面经 —— 吐血总结   目录 1. Tencent 2. 阿里 3. 百度 更好阅读,请移步这里 聊之前 最近暑期实习招聘已经开始,个人目前参加了阿里的内推及腾讯和百度的实习生招聘, ...

  3. 前端基础面试题(js部分)

      前端基础面试题(JS部分)   1.几种基本数据类型?复杂数据类型?值类型和引用数据类型?堆栈数据结构? 基本数据类型:Undefined.Null.Boolean.Number.String值类 ...

  4. web前端基础知识及快速入门指南

    web前端基础知识及快速入门指南 做前端开发有几个月了,虽然说是几个月,但是中间断断续续的上课.考试以及其它杂七杂八的事情,到现在居然一直感觉自己虽然很多前端的知识很眼熟,却也感觉自己貌似也知识在门口 ...

  5. web前端基础学习路线

    1.HTML和CSS的基础知识,完成网页的初步设计 2.JavaScript基础知识和DOM.BOM的学习 3.前端基础框架:CSS框架Bootstrap.JavaScript框架jquery的熟悉使 ...

  6. JS BOM DOM对象 select联动 计时器 时间 css操作 节点(标签 ) 查找标签 {前端基础之BOM和DOM}

    前端基础之BOM和DOM 前戏 到目前为止,我们已经学过了JavaScript的一些简单的语法.但是这些简单的语法,并没有和浏览器有任何交互. 也就是我们还不能制作一些我们经常看到的网页的一些交互,我 ...

  7. 前端基础之BOM和DOM day52

    前端基础之BOM和DOM   前戏 到目前为止,我们已经学过了JavaScript的一些简单的语法.但是这些简单的语法,并没有和浏览器有任何交互. 也就是我们还不能制作一些我们经常看到的网页的一些交互 ...

  8. 前端基础之JavaScript day51

    前端基础之JavaScript   JavaScript概述 JavaScript的历史 1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中) ...

  9. 浏览器环境下JavaScript脚本加载与执行探析之动态脚本与Ajax脚本注入

    在<浏览器环境下JavaScript脚本加载与执行探析之defer与async特性>中,我们研究了延迟脚本(defer)和异步脚本(async)的执行时机.浏览器支持情况.浏览器bug以及 ...

随机推荐

  1. SQL Server ---T-SQl基本语句

    T-SQL 是 SQL-Server 的结构化查询语言. 基本数据操作语言. 基础语句 先创建表 我后面的列子都是用的这一个表,列名啥的 就大概看看吧~~ 纯粹为了学习语句,语法~~所以先创建个表吧~ ...

  2. 浅谈js中如何动态添加表头/表列/表格内容

    我想很多童鞋用js动态向表格中添加数据很熟悉,而且也觉得非常简单!是的,对于写页面的童鞋来说,最喜欢写查询的页面了,动态向表格绑定数据.用for循环就可以轻松搞定. 如果我们的业务需求有所变化,可能我 ...

  3. 【万能的搜索,用广搜来解决DP问题】ZZNU -2046 : 生化危机 / HDU 1260:Tickets

    2046 : 生化危机 时间限制:1 Sec内存限制:128 MiB提交:19答案正确:8 题目描述 当致命的T病毒从Umbrella Corporation 逃出的时候,地球上大部分的人都死去了. ...

  4. AngularJs学习笔记3-服务及过滤器

    距离上次别博客有有一段时间了,因为最近公司和个人事情比较多,也因为学习新的知识所以耽搁了,也有人说Angularjs1.5没有人用了,没必要分享,我个人感觉既然开头了我就坚持把他写完,对一些还在使用或 ...

  5. 无法远程连接服务器上的mysql

    使用mysql管理工具连接服务器删过得mysql,显示连接被拒绝,但是在服务器上是可以登录mysql的. 无法远程连接通常以下几种情况: 首先,关闭mysql.        service mysq ...

  6. 页面嵌套frame,Selenium定位问题

    有时候,什么定位元素的方法都试过了,还是定位不到元素,就考虑frame切换问题 driver.switchTo().frame("定位到的frame元素"); //接下来就可以在这 ...

  7. python_正则表达式

    re.match函数 re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none. 函数语法: \[re.match(pattern, strin ...

  8. Failed to load JavaHL Library. These are the errors that were encountered:

    问题: Failed to load JavaHL Library.These are the errors that were encountered:no msvcp100 in java.lib ...

  9. ReactiveCocoa源码解读(二)

    上一篇解读了ReactiveCocoa的三个重要的类的底层实现,本篇继续. 一.RACMulticastConnection 1.应用 RACMulticastConnection: 用于当一个信号被 ...

  10. Windows环境下Mysql如何快速导入或恢复表为innodb的数据

    注: 一.这个是对Innodb的数据恢复.MyISAM不需要这么麻烦,只要数据文件存在直接复制过去就可以. 二.该方法只适用于 1:想要恢复或者导入表的ibd文件和frm文件 2:你不仅需有ibd和f ...