javaScript教程(三)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 浏览器模型 浏览器环境概述 https://wangdoc.com/javascript/bom/indexeddb.html JavaScript 是浏览器的内置脚本语言。也就是说,浏览器内置了 JavaScript 引擎,并且提供各种接口,让 JavaScript 脚本可以控制浏览器的各种功能。

浏览器模型

浏览器环境概述

JavaScript 是浏览器的内置脚本语言。也就是说,浏览器内置了 JavaScript 引擎,并且提供各种接口,让 JavaScript 脚本可以控制浏览器的各种功能。一旦网页内嵌了 JavaScript 脚本,浏览器加载网页,就会去执行脚本,从而达到操作浏览器的目的,实现网页的各种动态效果。

这里开始介绍浏览器提供的各种 JavaScript 接口。首先,介绍 JavaScript 代码嵌入网页的方法

代码嵌入网页的方法

网页中嵌入 JavaScript 代码,主要有四种方法:

script 元素嵌入代码

<script>
  var x = 1 + 5;
  console.log(x);
</script>

1.text/javascript:这是默认值,也是历史上一贯设定的值。如果你省略type属性,默认就是这个值。对于老式浏览器,设为这个值比较好

2.application/javascript:对于较新的浏览器,建议设为这个值

由于

<script id="mydata" type="x-custom-data">
  console.log('Hello World');
</script>

浏览器不会执行也不会显示内容,因为不认识它的type属性;但是,这个

document.getElementById('mydata').text // console.log('Hello World');

script 元素加载外部脚本

<script src="https://www.example.com/script.js"></script>

如果脚本文件使用了非英语字符,还应该注明字符的编码

<script charset="utf-8" src="https://www.example.com/script.js"></script>

所加载的脚本必须是纯的 JavaScript 代码,不能有HTML代码和

<script charset="utf-8" src="example.js">
  console.log('Hello World!');
</script>

为了防止攻击者篡改外部脚本,script标签允许设置一个integrity属性,写入该外部脚本的 Hash 签名,用来验证脚本的一致性

<script src="/assets/application.js" integrity="sha256-TvVUHzSfftWg1rcfL6TIJ0XKEGrgLyEq6lEpcmrG9qs="></script>

上面代码中,script标签有一个integrity属性,指定了外部脚本/assets/application.js的 SHA256 签名。一旦有人改了这个脚本,导致 SHA256 签名不匹配,浏览器就会拒绝加载

事件属性

网页元素的事件属性(比如onclick和onmouseover),可以写入 JavaScript 代码。当指定事件发生时,就会调用这些代码

<button id="myBtn" onclick="console.log(this.id)">点击</button> //如果有多个语句,使用分号分隔即可

URL 协议

URL 支持javascript:协议,即在 URL 的位置写入代码,使用这个 URL 的时候就会执行 JavaScript 代码

<a href="javascript:console.log('Hello')">点击</a>

浏览器的地址栏也可以执行javascript:协议。将javascript:console.log('Hello')放入地址栏,按回车键也会执行这段代码;如果 JavaScript 代码返回一个字符串,浏览器就会新建一个文档,展示这个字符串的内容,原有文档的内容都会消失

<a href="javascript: new Date().toLocaleTimeString();">点击</a>

上面代码中,用户点击链接以后,会打开一个新文档,里面有当前时间;如果返回的不是字符串,那么浏览器不会新建文档,也不会跳转

<a href="javascript: console.log(new Date().toLocaleTimeString())">点击</a>

javascript:协议的常见用途是书签脚本 Bookmarklet。由于浏览器的书签保存的是一个网址,所以javascript:网址也可以保存在里面,用户选择这个书签的时候,就会在当前页面执行这个脚本。为了防止书签替换掉当前文档,可以在脚本前加上void,或者在脚本最后加上void 0

<a href="javascript: void new Date().toLocaleTimeString();">点击</a>
<a href="javascript: new Date().toLocaleTimeString();void 0;">点击</a>

script 元素

工作原理

浏览器加载 JavaScript 脚本,主要通过

1.浏览器一边下载 HTML 网页,一边开始解析;也就是说,不等到下载完,就开始解析

2.解析过程中,浏览器发现

3.如果

4.JavaScript 引擎执行完毕,控制权交还渲染引擎,恢复往下解析 HTML 网页

加载外部脚本时,浏览器会暂停页面渲染,等待脚本下载并执行完成后再继续渲染;原因是 JavaScript 代码可以修改 DOM,所以必须把控制权让给它,否则会导致复杂的线程竞赛的问题。如果外部脚本加载时间很长(一直无法完成下载),那么浏览器就会一直等待脚本下载完成,造成网页长时间失去响应,浏览器就会呈现“假死”状态,这被称为“阻塞效应”。为了避免这种情况,较好的做法是将

<head>
  <script>
    console.log(document.body.innerHTML);
  </script>
</head>
<body></body>

上面代码执行时会报错,因为此时document.body元素还未生成

一种解决方法是设定DOMContentLoaded事件的回调函数

<head>
  <script>
    document.addEventListener(
      'DOMContentLoaded',
      function (event) {
        console.log(document.body.innerHTML);
      }
    );
  </script>
</head>

DOMContentLoaded事件只有在 DOM 结构生成之后才会触发

另一种解决方法是使用

<script src="jquery.min.js" onload="console.log(document.body.innerHTML)"></script>

但是,如果将脚本放在页面底部,就可以完全按照正常的方式写,上面两种方式都不需要。如果有多个script标签,比如下面这样:

<script src="a.js"></script>
<script src="b.js"></script>

浏览器会同时并行下载a.js和b.js,但是,执行时会保证先执行a.js,然后再执行b.js,即使后者先下载完成,也是如此。也就是说,脚本的执行顺序由它们在页面中的出现顺序决定,这是为了保证脚本之间的依赖关系不受到破坏。当然,加载这两个脚本都会产生“阻塞效应”,必须等到它们都加载完成,浏览器才会继续页面渲染。解析和执行 CSS,也会产生阻塞。Firefox 浏览器会等到脚本前面的所有样式表,都下载并解析完,再执行脚本;Webkit则是一旦发现脚本引用了样式,就会暂停执行脚本,等到样式表下载并解析完,再恢复执行。

此外,对于来自同一个域名的资源,比如脚本文件、样式表文件、图片文件等,浏览器一般有限制,同时最多下载6~20个资源,即最多同时打开的 TCP 连接有限制,这是为了防止对服务器造成太大压力。如果是来自不同域名的资源,就没有这个限制。所以,通常把静态文件放在不同的域名之下,以加快下载速度

defer 属性

为了解决脚本文件下载阻塞网页渲染的问题,一个方法是对

<script src="a.js" defer></script>
<script src="b.js" defer></script>

上面代码中,只有等到 DOM 加载完成后,才会执行a.js和b.js

defer属性的运行流程如下:

1.浏览器开始解析 HTML 网页

2.解析过程中,发现带有defer属性的

3.浏览器继续往下解析 HTML 网页,同时并行下载

4.浏览器完成解析 HTML 网页,此时再回过头执行已经下载完成的脚本

有了defer属性,浏览器下载脚本文件的时候,不会阻塞页面渲染。下载的脚本文件在DOMContentLoaded事件触发前执行(即刚刚读取完

目录
相关文章
|
1月前
|
JavaScript 前端开发
js教程——函数
js教程——函数
32 4
|
4月前
|
JavaScript
vue中使用 HotKeys.js 教程(按键响应、快捷键开发)
vue中使用 HotKeys.js 教程(按键响应、快捷键开发)
197 0
|
6月前
|
Web App开发 JavaScript 前端开发
《手把手教你》系列技巧篇(三十九)-java+ selenium自动化测试-JavaScript的调用执行-上篇(详解教程)
【5月更文挑战第3天】本文介绍了如何在Web自动化测试中使用JavaScript执行器(JavascriptExecutor)来完成Selenium API无法处理的任务。首先,需要将WebDriver转换为JavascriptExecutor对象,然后通过executeScript方法执行JavaScript代码。示例用法包括设置JS代码字符串并调用executeScript。文章提供了两个实战场景:一是当时间插件限制输入时,用JS去除元素的readonly属性;二是处理需滚动才能显示的元素,利用JS滚动页面。还给出了一个滚动到底部的代码示例,并提供了详细步骤和解释。
88 10
|
6月前
|
JavaScript 前端开发 网络安全
【网络安全 | 信息收集】JS文件信息收集工具LinkFinder安装使用教程
【网络安全 | 信息收集】JS文件信息收集工具LinkFinder安装使用教程
348 4
|
1月前
|
JavaScript 前端开发 Java
Node.js 教程
10月更文挑战第1天
38 0
|
3月前
|
JavaScript NoSQL 前端开发
|
4月前
|
JSON JavaScript 数据格式
vue 绘制波形图 wavesurfer.js (音频/视频) 【实用教程】
vue 绘制波形图 wavesurfer.js (音频/视频) 【实用教程】
392 3
|
4月前
|
JavaScript
vue 农历日期转公历日期(含插件 js-calendar-converter 使用教程)
vue 农历日期转公历日期(含插件 js-calendar-converter 使用教程)
236 0
|
4月前
|
开发框架 监控 JavaScript
企业级node.js开发框架 【egg.js】 实用教程
企业级node.js开发框架 【egg.js】 实用教程
68 0
|
4月前
命令行加载特效 【cli-spinner.js】 实用教程
命令行加载特效 【cli-spinner.js】 实用教程
46 0