XingYun blog
  • JS基础

    • 图解js原型链
    • JS Event Loop
    • 对象的底层数据结构
    • 让你的JavaScript代码简单又高效
    • 函数参数按值传递
    • 判断数据类型
    • 浮点数精度问题和解决办法
    • 常用方法snippet
    • 实现Promise
    • 防抖和节流
    • 巧用sort排序
  • CSS && HTML

    • CSS也需要性能优化
    • class命名规范
    • em、px、rem、vh、vw 区别
    • CSS揭秘阅读笔记
  • 浏览器

    • 浏览器是如何渲染页面的
    • 重排和重绘
    • BOM浏览器对象模型
    • DOM事件
    • 浏览器存储
  • 数据结构

    • JS实现链表
    • JS实现栈与栈应用
    • JS实现常见排序
    • 哈夫曼编码
    • MD5算法
  • vue原理浅析

    • Vue虚拟dom与Diff算法
    • 前端打包文件的缓存机制
    • vue数组为什么不是响应式
    • v-for为什么不能用index做key
  • 前端工程化

    • 浏览器是如何渲染页面的
    • 前端打包需要gzip压缩吗
    • 前端打包文件的缓存机制
    • webpack loader和plugin
  • 轮子&&组件库

    • 实现水波浪进度球
  • 文字转语音mp3文件
  • 文件上传前后端实现
  • moment.js给定时间获取自然月、周的时间轴
  • 实现文件上传功能
  • 批量下载照片
  • leaflet改变坐标原点
  • 网络

    • 有了MAC地址 为什么还需要IP地址
    • 为什么IP地址老是变
    • 我们为什么需要IPV6
    • TCP与UDP
  • 计算机组成原理

    • ASCII、Unicode、UTF-8和UTF-16
  • VSCode

    • VSCode图片预览插件 Image preview
    • rsync:linux间的高效传输工具

XingYun

冲!
  • JS基础

    • 图解js原型链
    • JS Event Loop
    • 对象的底层数据结构
    • 让你的JavaScript代码简单又高效
    • 函数参数按值传递
    • 判断数据类型
    • 浮点数精度问题和解决办法
    • 常用方法snippet
    • 实现Promise
    • 防抖和节流
    • 巧用sort排序
  • CSS && HTML

    • CSS也需要性能优化
    • class命名规范
    • em、px、rem、vh、vw 区别
    • CSS揭秘阅读笔记
  • 浏览器

    • 浏览器是如何渲染页面的
    • 重排和重绘
    • BOM浏览器对象模型
    • DOM事件
    • 浏览器存储
  • 数据结构

    • JS实现链表
    • JS实现栈与栈应用
    • JS实现常见排序
    • 哈夫曼编码
    • MD5算法
  • vue原理浅析

    • Vue虚拟dom与Diff算法
    • 前端打包文件的缓存机制
    • vue数组为什么不是响应式
    • v-for为什么不能用index做key
  • 前端工程化

    • 浏览器是如何渲染页面的
    • 前端打包需要gzip压缩吗
    • 前端打包文件的缓存机制
    • webpack loader和plugin
  • 轮子&&组件库

    • 实现水波浪进度球
  • 文字转语音mp3文件
  • 文件上传前后端实现
  • moment.js给定时间获取自然月、周的时间轴
  • 实现文件上传功能
  • 批量下载照片
  • leaflet改变坐标原点
  • 网络

    • 有了MAC地址 为什么还需要IP地址
    • 为什么IP地址老是变
    • 我们为什么需要IPV6
    • TCP与UDP
  • 计算机组成原理

    • ASCII、Unicode、UTF-8和UTF-16
  • VSCode

    • VSCode图片预览插件 Image preview
    • rsync:linux间的高效传输工具
  • leaflet改变坐标原点
  • 补间动画gsap与tween
  • 文字转语音mp3文件
  • JavaScript引入
    • JavaScript高级程序设计阅读笔记
    • Javascript函数参数按值传递传递
    • JS防抖和节流
    • 手写JS常用方法
    • 手写Promise
    • JS Event Loop
    • 重排和重绘
    • em、px、rem、vh、vw 区别
    • css也需要性能优化
    • 图解 js 原型链
    • js函数参数按值传递
    • BOM浏览器对象模型
    • DOM
    • 事件
    • js对象数组sort按需排序
    • 文件上传功能技术选型和前后端实现
    • 前端图片处理
    • 让你的JavaScript代码简单又高效
    • BEM:class命名规范
    • 前端规范-CSS属性那么多(杂),怎么排序
    • TypeScript Tips
    • jsx
    • canvas基础
    • 前端日志
    • 浏览器存储
    • CSS世界阅读笔记
    • CSS揭秘阅读笔记
    • js变量命名常用规范词
    • 你不知道的JavaScript阅读笔记
    • js对象的底层数据结构
    • js判断数据类型
    • JS浮点数精度问题和解决办法
    • js作用域
    • js堆栈溢出和内存泄漏
    • 浏览器是如何渲染页面的
    • 疑难杂症和踩坑问题合集
    • 免费在线API收集
    • 原生JS实现Ajax请求
    • cookie、session、localStorage、sessionStorage的区别
    • Sass与Less
    • arrayBuffer、blob、file对象
    • TypeScript基础
    • 前端
    XingYun
    2022-02-13
    目录

    JavaScript引入

    参考:JavaScript高级程序设计(第4版)

    使用 script 的方式有两种:通过它直接在网页中嵌入 JavaScript 代码,以及通过它在网页中包含外部 JavaScript 文件。

    这里要讨论的是第二种方式: 外部引入

    # html 中的 script 元素

    我们一般这样引入 JavaScript

    <script src="example.js"></script>
    
    1

    注意 按照惯例,外部 JavaScript 文件的扩展名是.js。这不是必需的,因为浏览器不会检查所包含 JavaScript 文件的扩展名。这就为使用服务器端脚本语言动态生成 JavaScript 代码,或者在浏览器中将 JavaScript 扩展语言(如 TypeScript,或 React 的 JSX)转译为 JavaScript 提供了可能性。不过要注意,服务器经常会根据文件扩展来确定响应的正确 MIME 类型。如果不打算使用.js 扩展名,一定要确保服务器能返回正确的 MIME 类型。

    另外,使用了 src 属性的 script 元素不应该再在 script 和标签中再包含其他 JavaScript 代码。

    如果两者都提供的话,则浏览器只会下载并执行脚本文件,从而忽略行内代码。

    script 可以引入外部域的 JavaScript 文件

    script 元素的一个最为强大、同时也备受争议的特性是,它可以包含来自外部域的 JavaScript 文件。

    跟 img 元素很像,script 元素的 src 属性可以是一个完整的 URL,而且这个 URL 指向的资源可以跟包含它的 HTML 页面不在同一个域中,比如这个例子:

    <script src="http://www.somewhere.com/afile.js"></script>
    
    1

    浏览器在解析这个资源时,会向 src 属性指定的路径发送一个 GET 请求,以取得相应资源,假定是一个 JavaScript 文件。

    这个初始的请求不受浏览器同源策略限制,但返回并被执行的 JavaScript 则受限制。当然,这个请求仍然受父页面 HTTP/HTTPS 协议的限制。

    来自外部域的代码会被当成加载它的页面的一部分来加载和解释。这个能力可以让我们通过不同的域分发 JavaScript。

    注意:引用了放在别人服务器上的 JavaScript 文件时要格外小心,因为恶意的程序员随时可能替换这个文件。在包含外部域的 JavaScript 文件时,要确保该域是自己所有的,或者该域是一个可信的来源。

    script 标签的 integrity 属性是防范这种问题的一个武器,但这个属性也不是所有浏览器都支持。

    script 执行顺序

    不管包含的是什么代码,浏览器都会按照 script 在页面中出现的顺序依次解释它们,前提是它们没有使用 defer 和 async 属性。第二个 script 元素的代码必须在第一个 script 元素的代码解
    释完毕才能开始解释,第三个则必须等第二个解释完,以此类推。

    # script 标签位置

    过去,所有 script 元素都被放在页面的 head 标签内,如下面的例子所示:

    <!DOCTYPE html>
    <html>
      <head>
        <title>Example HTML Page</title>
        <script src="example1.js"></script>
        <script src="example2.js"></script>
      </head>
      <body>
        <!-- 这里是页面内容 -->
      </body>
    </html>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    这种做法的主要目的是把外部的 CSS 和 JavaScript 文件都集中放到一起。不过,把所有 JavaScript 文件都放在 head 里,也就意味着必须把所有 JavaScript 代码都下载、解析和解释完成后,才能开始渲染页面(页面在浏览器解析到 body 的起始标签时开始渲染)。

    对于需要很多 JavaScript 的页面,这会导致页面渲染的明显延迟,在此期间浏览器窗口完全空白。

    为解决这个问题,现代 Web 应用程序通常将所有 JavaScript 引用放在 body 元素中的页面内容后面,如下面的例子所示

    <!DOCTYPE html>
    <html>
      <head>
        <title>Example HTML Page</title>
      </head>
      <body>
        <!-- 这里是页面内容 -->
        <script src="example1.js"></script>
        <script src="example2.js"></script>
      </body>
    </html>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    这样一来,页面会在处理 JavaScript 代码之前完全渲染页面。用户会感觉页面加载更快了,因为浏览器显示空白页面的时间短了。

    # defer 与 async

    defer 与 async 都可以用来优化 script 的加载过程

    # defer 立即下载 延迟执行脚本

    HTML 4.01 为 script 元素定义了一个叫 defer 的属性。这个属性表示脚本在执行的时候不会改变页面的结构。

    也就是说,脚本会被延迟到整个页面都解析完毕后再运行。因此,在 script 元素上设置 defer 属性,相当于告诉浏览器立即下载,但延迟执行。

    <!DOCTYPE html>
    <html>
      <head>
        <title>Example HTML Page</title>
        <script defer src="example1.js"></script>
        <script defer src="example2.js"></script>
      </head>
      <body>
        <!-- 这里是页面内容 -->
      </body>
    </html>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    虽然这个例子中的 script 元素包含在页面的 head 中,但它们会在浏览器解析到结束的

    html 标签后才会执行。HTML5 规范要求脚本应该按照它们出现的顺序执行,因此第一个推迟的脚本会在第二个推迟的脚本之前执行,而且两者都会在 DOMContentLoaded 事件之前执行。不过在实际当中,推迟执行的脚本不一定总会按顺序执行或者在 DOMContentLoaded 事件之前执行,因此最好只包含一个这样的脚本。

    # async 异步执行脚本

    HTML5 为script元素定义了 async 属性。从改变脚本处理方式上看,async 属性与 defer 类似。

    当然,它们两者也都只适用于外部脚本,都会告诉浏览器立即开始下载。

    不过,与 defer 不同的是,标记为 async 的脚本并不保证能按照它们出现的次序执行,比如:

    <!DOCTYPE html>
    <html>
      <head>
        <title>Example HTML Page</title>
        <script async src="example1.js"></script>
        <script async src="example2.js"></script>
      </head>
      <body>
        <!-- 这里是页面内容 -->
      </body>
    </html>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    在这个例子中,第二个脚本可能先于第一个脚本执行。

    因此,重点在于它们之间没有依赖关系。给脚本添加 async 属性的目的是告诉浏览器,不必等脚本下载和执行完后再加载页面,同样也不必等到该异步脚本下载和执行后再加载其他脚本。正因为如此,异步脚本不应该在加载期间修改 DOM。

    #JavaScript
    上次更新: 2023/04/05, 09:41:10
    文字转语音mp3文件
    JavaScript高级程序设计阅读笔记

    ← 文字转语音mp3文件 JavaScript高级程序设计阅读笔记→

    最近更新
    01
    JavaScript-test
    07-20
    02
    二维码的原理
    07-20
    03
    利用ChatGPT优化代码
    07-20
    更多文章>
    Theme by Vdoing | Copyright © 2021-2023 XingYun | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式