总感觉一直在看各种零散的JS文章,但很多知识不成体系,容易忘却,加上前段时间面试,不停被基础问题打个措手不及,所以想自己看书整理一下这些知识。 以下只是一个菜鸟的学习笔记,算不上什么技术交流,如果有理解和表达错误的点或者冗余废话,还请原谅,欢迎指正和建议。
红宝书学习笔记【第1~2章】
第一章
基本都是js的发展历史,和js的宏观概念
为什么需要js
js出现之前,表单信息得通过服务端校验,但那时网络的速度还很慢,用户的体验极差,所以“网景”公司决定开发一个客户端的脚本语言来处理处理简单的数据验证。
js的实现
完整的js包含: 核心(ECMAScript):由ECMA-262 定义并提供核心技能 文档对象模型(DOM):提供与网页内容交互的方法和接口 浏览器对象模型(BOM):提供与浏览器交互的方法和接口
第二章 HTML 中的 JavaScript
<script> 元素
1. 可选属性
-
async: 表示立即异步下载脚本, 不阻止其他页面动作, 比如下载资源或等待其他脚本加载. 只对外部脚本有效.
-
defer: 表示脚本可以延迟到文档完全被解析和现实后再执行, 只对外部脚本文件有效.
-
src: 表示包含要执行的外部代码文件
-
charset: 使用src属性指定的代码字符集, 大多数浏览器不在乎它的值.
-
crossorigin: 配置相关请求的CORS设置.
-
integrity:允许比对接收到的资源和指定的加密签名以验证子资源完整性
-
language: 废弃, 用于表示代码块中的脚本语言(如"JavaScript", "VBScript"). 大多数浏览器会忽略该属性.
-
type: 代替language, 表示代码块中的脚本语言内容类型(MIME). 常用来设置为"module", 让代码被当做es6模块, 从而允许代码中使用
import和export关键字.
2. 使用方式
- 通过它直接在网页中嵌入js代码(行内方式)
- 通过它在网页中包含其他外部js文件(外链方式)
注意事项:
- 不论哪种方式, 在解释js代码时都会阻塞页面(阻塞时间包含下载文件的时间).
- 按照惯例, 外部js文件的扩展名应该是
.js, 但浏览器不会检查所包含js文件的扩展名, 所以扩展名不是必须的. 这为服务器端动态生成js代码和在浏览器中将ts和jsx等扩展语言转为js提供了可能性. 需要注意, 服务器端会根据文件扩展名来确定响应的正确MIME类型. - 使用了
src属性的script标签中不应该再包含行内的js代码. 该情况下浏览器会加载外部文件, 忽略行内js代码.
3. <script>和浏览器跨域
与<img>元素相似, <script>的src可以是完整的url地址, 而且该url可以指向与当前网页不在同一域下的资源.
浏览器解析该资源时, 会向 src 属性指定的路径发出 GET 请求(该请求受网页的 HTTP/HTTPS 协议的限制), 已取得文件资源. 该请求不受浏览器同源策略的制约, 但加载并执行的js代码会受到限制.
因为外部文件可能被程序员恶意替换, 所以这种方式并不安全, <script>标签的 integrity 属性是防范这种问题的一个武器,但这个属性也不是所有浏览器都支持。
4. <script>的加载和执行时机
一般情况
默认情况下, 浏览器按照<script>的出现顺序依次解释它们, 第二个<script>必须在第一个<script>解析完毕才能开始解释.
过去, 所有<script>都被放在<head>标签中, 目的是将外部的css和js都集中放在一起. 但这种做法意味着所有js代码都加载,解析和执行后, 才开始渲染页面 ( 浏览器解析到<body>标签时开始渲染 ). 这导致页面渲染被推迟,白屏时间增加.
现在, 通常将<script>标签都放在<body>标签的最后.
推迟(defer) 和 异步(async)
1. defer
该属性只对外部脚本文件有效.
该属性表示, 脚本在执行时不会改变页面结构, 将脚本延迟到整个页面解析结束( 浏览器解析到<\html> )再运行.
理论上, 被延迟的多个脚本会按照<script>标签的顺序执行, 被延迟执行的脚本会在 DOMContentLoaded事件之前执行, 但实际上被延迟的脚本不一定会按顺序执行, 也不一定都在DOMContentLoaded事件之前执行, 所以最好只包含一个这样的脚本.
2. async
该属性与defer类似, 都只适用于外部脚本文件, 都不能改变页面结构, 都会让浏览器立即开始下载文件(异步), 但标记为async的脚本不保证按照出现顺序执行, 而是在加载结束后执行.
被async标记的脚本在下载和执行时, 不阻塞页面的加载, 也不影响其他js脚本的加载.
异步脚本保证会在页面的 load 事件前执行,但可能会在 DOMContentLoaded之前或之后。
3. defer 和 async 的不同点
- 出现时间不同, defer是HTML4.01 出现的, async是在HTML5.
- 执行时间不同, defer的脚本会在页面解析结束后执行, async的脚本会在脚本加载结束后执行.
- defer理论上按照
<script>标签出现的顺序执行, async不按照出现顺序执行.
动态加载脚本
我们可以通过 DOM API, 通过创建<script>标签动态加载脚本.
在没有将<script>标签加入到页面之前, 该脚本不会被加载. 而且该方式默认以 async 方式加载脚本. 但并不是所有浏览器都支持 async 属性, 所以为了统一脚本的加载行为, 可以在创建<script>标签时, 设置其 async 属性为 false.
以这种方式加载资源时, 对浏览器的预加载器不可见, 这会严重影响它们在资源加载队列的优先级. 所以可以在文档头部显式声明他们:
<link ref="preload" href="example.js">
<noscript>
<noscript>元素可以包含任何可以出现在<body>中的 HTML 元素,<script>除外。
在下列两种情况下,浏览器将显示包含在<noscript>中的内容:
- 浏览器不支持脚本;
- 浏览器对脚本的支持被关闭。
任何一个条件被满足,包含在<noscript>中的内容就会被渲染。