【前端基础】动态脚本与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技术。

时间: 2024-10-25 14:06:22

【前端基础】动态脚本与JSONP的相关文章

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

在<浏览器环境下JavaScript脚本加载与执行探析之defer与async特性>中,我们研究了延迟脚本(defer)和异步脚本(async)的执行时机.浏览器支持情况.浏览器bug以及其他的细节问题.而除了defer和async特性,动态脚本和Ajax脚本注入也是两种常用的创建无阻塞脚本的方法.总的来看,这两种方法都能达到脚本加载不影响页面解析和渲染的作用,但是在不同的浏览器中,这两种技术所创建的脚本的执行时机还是有一定差异,今天我们再来探讨一下通过动态脚本技术和Ajax注入的脚本在这些方

前端基础html

前端基础之html HTML 初识 web服务本质 import socket def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost',8081)) sock.listen(5) while True: print("server is working.....") conn, address = sock.accept() request = conn.re

day 46 前端基础 基本框架

HTML标签格式 HTML标签是由尖括号包围的关键字,如<html>, <div>等 HTML标签通常是成对出现的,比如:<div>和</div>,第一个标签是开始,第二个标签是结束.结束标签会有斜线. 也有一部分标签是单独呈现的,比如:<br/>.<hr/>.<img src="1.jpg" />等. 标签里面可以有若干属性,也可以不带属性. 标签的语法: <标签名 属性1="属性值1

前端基础:HTML标签(下)

前端基础HTML标签(下) 1.表单 表单的功能主要用于向服务器传输数据,从而实现客户端与Web服务器的交互.表单能够包含input系列标签,比如:文本字段.复选框.单选按钮.提交按钮等:表单还包含textarea.select和label标签: 表单的属性:action,将表单数据提交到指定服务器的某个程序,程序收到表单提交过来的数据(即表单数据)做相应处理,比如:https://baidu.com:**method**,表单的提交方式get/post/update等,默认为get: 注意 f

前端基础之BOM和DOM:

目录 前端基础之BOM和DOM 前言 window对象 BOM与DOM操作 DOM学习流程 一些常用的Window方法: window的子对象 navigator对象(了解即可) screen对象(了解即可) history对象(了解即可) location对象 弹出框 计时相关 DOM HTML DOM 树 查找标签 直接查找 间接查找 节点操作 创建节点 添加节点 删除节点: 替换节点: 获取值操作 对类属性操作 class的操作 指定CSS操作 事件 常用事件 绑定方式: window.o

《web 前端基础到实战系列课程》

<web 前端基础到实战系列课程> 摘要: mod_expires&mod_headers可以减少10%左右的重复请求,让重复的用户对指定的页面请求结果都CACHE在本地,根本不向服务器发出请求. 在使用之前,首先要确认一下"mod_expires"模组是否有启用.如果是自己安装Apache来架设网页主机的话,这里我们可以透过编辑Apache的"httpd.conf"设定档来处理 一.浏览器缓存原理 将该行前面的"#"字号删除

【开源】.Net 动态脚本引擎NScript

开源地址: https://git.oschina.net/chejiangyi/NScript 开源QQ群: .net 开源基础服务  238543768 .Net 动态脚本引擎 NScript   用于解决.net环境windows系统下类似java中Grovvy的功能和方向.在互联网项目可以用来做一些功能,如动态营销活动(营销业务解耦和剥离),规则引擎,流程引擎,windows运维脚本,源码式插件开发等. 使用方式 包括exe Main方式,程序集方式,应用程序域三种方式. 最终编译文件

进击的Python【第十三章】:Web前端基础之HTML与CSS样式

进击的Python[第十四章]:Web前端基础之HTML与CSS样式 一.web框架的本质 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. #!/usr/bin/env python #coding:utf-8 import socket def handle_request(client): buf = client.recv(1024) client.send("HTTP/1.1 200 OK\r\n\r\n")

好程序员web前端学习路线分享前端基础面试题

好程序员web前端学习路线分享前端基础面试题,希望对大家有所帮助. 1.HTML语义化的理解? 答案:HTML语义化就是让页面的内容结构化,便于对浏览器.搜索引擎解析:在没有样式CSS的情况下也以一种文档格式显示,并且是容易阅读的:搜索引擎的爬虫依赖于标记来确定上下文和各个关键字的权重,利于SEO:使阅读源代码的人对网站更容易将网站分块,便于阅读维护理解. 2.父元素透明,但是又不影响子元素的透明度怎么实现? 答案:方法一:用rgba 方法二:再加上一层与父元素同级的div装载子元素,定位到子元