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

  • 相关阅读:
    linux 常用操作指令(随时更新)
    Spring @Scheduled应用解析
    H5的FormData对象完成ajax上传文件multiFile
    微服务的4个设计原则和19个解决方案
    微服务实战(六):如何做好服务拆分?
    微服务实战(五):微服务化之缓存的设计
    微服务实战(四):微服务化之无状态化与容器化
    微服务实战(三):以MySQL为例,从原理上理解那些所谓的数据库军规
    微服务实战(二):微服务的接入层设计与动静资源隔离
    微服务实战(一):微服务化的基石——持续集成
  • 原文地址:https://www.cnblogs.com/leegent/p/7499532.html
Copyright © 2020-2023  润新知