前端训练营——JavaScript课件:一:JavaScript基本介绍
一:JavaScript基本介绍
JavaScript是一种广泛使用的脚本语言,它允许开发人员为Web应用程序添加交互性和动态性。JavaScript最初是由Netscape Communications在1995年开发的,它已经成为了Web开发的标准之一。
JavaScript的主要用途是创建交互性,例如表单验证、动态内容更新、动画效果和弹出窗口等。它也可以用于创建Web应用程序的后端逻辑,例如数据验证、服务器通信和数据库操作等。
JavaScript代码可以嵌入到HTML文档中,也可以作为外部脚本文件链接到HTML文档中。它可以直接访问文档对象模型(DOM),从而可以操作HTML元素和属性,并响应用户事件。
JavaScript具有许多优点,例如易于学习、跨平台性、高度灵活性、可扩展性和广泛的支持。然而,它也有一些缺点,例如性能问题、代码混淆和安全性问题等。
一个完整的JavaScript实现应该由以下三个部分构成:ECMAScript、DOM、BOM
ECMAScript: 规定了JS的变成语法和基础核心知识,是所有浏览器厂商都遵守的JS语法工业标准。
DOM: 文档对象模型(Document Object Model),提供访问和操作网页内容的方法和接口,通过document.element对象实现。
BOM:浏览器对象模型(Browser Object Model),提供与浏览器交互的方法和接口,通过 window 对象实现。
1.1:ECMAScript
ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer Manufacturers Association)通过ECMA-262标准化的脚本程序设计语言。这种语言在万维网上应用广泛,它往往被称为JavaScript或JScript,但实际上后两者是ECMA-262标准的实现和扩展。
ECMAScript标准没有参照Web浏览器,大致说来,它规定了这门语言的下列组成部分:
语法
类型
语句
关键字
保留字
操作符
对象
具体语法略,大家都有编程语言基础,这些东西都是相似的,看看菜鸟文档几小时就会了。
不过需要注意的是,ECMAScript也在不断发展,至今已经有很多版本。从ECMAScript第6版开始,每年发布一个ECMAScript版本,因此ECMAScript版本有了很多名字,包括全名ECMAScript 6、简写ES6、年份命名ECMAScript 2015、年份简写ES2015。最常见的名字还是ES6,之后推出的 ES7、ES8 等同理。
我们常把5.1之前的ECMAScript版本统称做ES5,将6版本之后的版本统称做ES6(因为从 2015 年起,ECMAScript 终于步入正轨,每年发布一次版本,到了2021年,已经发布了6个版本了,实在太多,所以用变革了JavaScript时代的ES6作为后续版本的代称)。
划重点,Web前端招聘的岗位要求中,经常出现的ES6,不仅仅是ES2015这个版本,而是指代ES2015和其后每年发布的ECMAScript版本。如果大家想去找工作,ES新特性最好都学会。
可以通过TC39了解ES新特性,TC39是一个推动JavaScript发展的委员会,由众多互联网公司和各大主流浏览器厂商的代表共同组建,是一种开放性的指导委员会,所有的ECMAScript标准都是由TC39委员会制定的。传送门:tc39
image
1.2:DOM
1.2.1:DOM树
文档对象模型(DOM,Document Object Model)是针对 XML但经过扩展用于 HTML的应用程序编程接口(API,Application Programming Interface)。DOM把整个页面映射为一个多层节点结构。HTML 或 XML页面中的每个组成部分都是某种类型的节点,这些节点又包含着不同类型的数据。
DOM标准规定HTML文档中的每个成分都是一个节点(node):
文档节点(document对象):代表整个文档
元素节点(element 对象):代表一个元素(标签)
文本节点(text对象):代表元素(标签)中的文本
属性节点(attribute对象):代表一个属性,元素(标签)才有属性
注释是注释节点(comment对象)
image
看下面这个 HTML页面:
<html> <head> <title>sample Page</title> </head> <body> <p>Hello World!</p> </body> </html>
在 DOM中,这个页面可以通过下图所示的分层节点图表示:
image
借助 DOM提供的 API,开发人员可以轻松自如地删除、添加、替换或修改任何节点。
JavaScript 能够改变页面中的所有 HTML 元素
JavaScript 能够改变页面中的所有 HTML 属性
JavaScript 能够改变页面中的所有 CSS 样式
JavaScript 能够对页面中的所有事件做出反应(鼠标点击事件,鼠标移动事件等)
下面是一段简单的演示代码,大家可以自己跑一跑:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> <div>JavaScript 能够改变页面中的所有HTML元素</div> <button onclick="changeDOM()">click</button> <a href="https://www.baidu.com" target="_blank" style="display: block;">JavaScript 能够改变页面中的所有HTML属性</a> <button onclick="changeAttribute()">click</button> <div>JavaScript 能够改变页面中的所有CSS样式</div> <button onclick="changeCSS()">click</button> <div>JavaScript 能够对页面中的所有事件做出反应</div> <button>略,上面已经展示了三个点击事件</button></body> <script> var i = 1; function changeDOM() { document.getElementsByTagName("div")[0].innerHTML = "HTML元素被改变了" + i + "次"; i++; } function changeAttribute() { var dom = document.getElementsByTagName("a")[0]; dom.setAttribute("href", "https://www.csdn.net"); } function changeCSS() { document.getElementsByTagName("div")[1].style.color = "red"; }</script> </html>
image
1.2.2:浏览器渲染
浏览器的主要功能就是向服务端发送请求,下载解析资源显示在浏览器上。将网页内容展示到浏览器上的过程,这其实就是渲染引擎完成的。渲染引擎有很多种,这里以 webkit(chrome) 为例。
image
当浏览器获得一个html文件时,会自上而下的加载,并在加载过程中进行解析渲染。
获取 HTML 文件并进行解析,生成 DOM (Document Object Model/文档对象模型)树;
遇到 script 标签时,DOM 树构建将暂停,直至脚本执行完毕;
解析 HTML 的同时也会解析 CSS,生成 CSSOM (CSS Object Model)树;
将 DOM 树和 CSSOM 树结合,去除不可见元素(很重要),生成渲染树 (Render Tree);
根据生成的渲染树,生成布局 (Layout) *(这是一次回流)*,得到节点的几何信息(位置,大小);
根据渲染树以及回流得到的几何信息,进行绘制 (Painting) (这是一次重绘),绘制完毕后进行 Display 展示。
1.2.3:回流与重绘
回流也叫重排,当 DOM 的变化影响了元素的几何信息(位置、尺寸大小等),浏览器需要重新计算元素的几何属性,将其安放在界面的正确位置,这个过程叫做回流。
回流的触发时机:
页面初始渲染,这是开销最大的一次回流,并且避免不了;
添加或删除可见的 DOM 元素;
元素的位置发生变化;
元素的尺寸发生变化(包括外边距、内边距、边框大小、高度和宽度等);
元素内容发生变化(例如文字数量、字体、图片大小等);
元素字体大小改变;
改变浏览器窗口尺寸(例如 resize 事件发生时);
激活 CSS 伪类(例如 :hover);
设置 style 属性的值,因为通过设置 style 属性改变节点样式的话,每一次设置都会触发一次回流;
查询某些属性或调用某些计算方法:offsetWidth、offsetHeight 等,除此之外,当我们调用 getComputedStyle 方法,或者 IE 里的 currentStyle 时,也会触发回流,原理是一样的,都为求一个 “即时性” 和 “准确性” 。
由于浏览器渲染界面是基于流式布局模型的,所以触发回流时会对周围 DOM 重新排列,影响的范围有两种:
全局范围:从根节点 html 开始对整个渲染树进行重新布局;
局部范围:对渲染树的某部分或某一个渲染对象进行重新布局。
重绘:当一个元素的外观发生变化,但没有改变布局,重新把元素外观绘制出来的过程。
重绘的触发时机:
可见性(visibility)和透明度(opacity)的改变;
颜色的改变;
背景的改变;
阴影、轮廓的改变;
文本方向(text-decoration)的改变等。
回流与重绘的关系:
回流一定导致重绘,重绘不一定导致回流。
每个页面初始化渲染时至少触发一次回流和重绘。
回流和重绘的代价都很高昂,频繁回流重绘,会破坏用户体验,让页面显示变迟缓。所以我们要尽可能避免频繁触发回流和重绘,尤其是回流。
如何尽量避免回流重绘:
浏览器对于回流和重绘的优化
浏览器会维护一个队列,把所有会引起回流、重绘的操作放入这个队列,等队列中的操作到了一定数量或者到了一定的时间间隔,浏览器就会 flush 队列,进行一个批处理。这样就会让多次的回流、重绘变成一次回流重绘。
但当你获取布局信息的操作的时候,例如 offsetTop 等,为了保证获取结果的准确性,就会打破浏览器的这种优化策略,强制浏览器提前 flush 队列。
css 中避免回流和重绘
减少回流范围,尽量将需要回流的内容固定在局部范围。
不要使用 table 布局,可能很小的一个改动会造成整个 table 的重新布局。不得已使用 table 的场景,可以设置 table-layout: auto; 或者 table-layout: fixed; 这样可以让 table 一行一行的渲染,同时可可以限制回流的影响范围。
集中修改样式。这样可以尽可能利用浏览器的优化机制,一次回流重绘就完成渲染。
避免设置多项内联样式。
如果想设定元素的样式,可以通过改变元素的 class 类名(尽可能在 DOM 树的最里层)。
将 DOM 离线。通过设置元素属性 display: none; 将其从页面上去掉,然后再进行后续操作,这些后续操作将不会出发回流、重绘,最后通过 display 属性显示。另外,visibility: hidden 的元素只对重绘有影响,不影响回流。
使用 position: absolute / fixed; 脱离文档流。例如那些复杂的动画,对其设置 position: absolute / fixed; 尽可能地使元素脱离文档流,从而减少对其他元素的影响。
利用 transform translate 去代替 left top 的变换。
使用 css3 硬件加速,可以让 transform、opacity、filters 这些动画不会引起回流重绘。
避免使用 css 的 JavaScript 表达式。
将频繁回流或重绘的节点设置为图层。将节点设置为 video 或 iframe;为节点添加 will-change 属性。
js 中避免回流和重绘
减少直接操作 DOM 元素。不要一条一条地修改 DOM 的样式,改用 className 来控制。
分离读写操作。当需要 js 操作元素样式时,即将获取样式属性的操作集中执行,并缓存值,在需要设置样式属性时也集中处理,避免获取和设置的操作互相夹杂。因为获取、设置的操作都会引起回流。
动态插入多个节点时,可以使用文档碎片(DocumnetFragment),创建后一次插入,避免多次的渲染性能。DocumnetFragment 是一个保存多个元素的容器对象(保存在内存),当更新其中的一个或者多个元素时,页面不会更新。
不要把 DOM 节点的 offsetLeft 等属性值放在一个循环里当成循环里的变量。
使用 resize 事件时,做防抖和节流处理。
1.3:BOM
开发人员使用BOM(BOM,Browser Object Model)可以控制浏览器显示的页面以外的部分。而BOM真正与众不同的地方(也是经常会导致问题的地方),还是它作为JavaScript实现的一部分但却没有相关的标准。这个问题在HTML5中得到了解决,HTML5致力于把很多 BOM功能写入正式规范。HTML5发布后,很多关于BOM的困惑烟消云散。 从根本上讲,BOM只处理浏览器窗口和框架;但人们习惯上也把所有针对浏览器的JavaScript扩展算作 BOM的一部分。下面就是一些这样的扩展:
弹出新浏览器窗口的功能
移动、缩放和关闭浏览器窗口的功能
提供浏览器详细信息的navigator对象
提供浏览器所加载页面的详细信息的location对象
提供用户显示器分辨率详细信息的screen对象
对 cookies的支持
像XMLHttpRequest和IE的ActiveXObject这样的自定义对象。 由于没有BOM标准可以遵循,因此每个浏览器都有自己的实现。虽然也存在一些事实标准,例如要有window对象和navigator对象等,但每个浏览器都会为这两个对象乃至其他对象定义自己的属性和方法。现在有了HTML5,BOM实现的细节有望朝着兼容性越来越高的方向发展。
以下是一些简单示例:
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> <button onclick="jump()">跳转到百度</button> <button onclick="pop()">打开浏览器弹窗</button> <button onclick="width()">获取可用宽度</button></body> <script> function jump() { window.location.href = "https://www.baidu.com"; } function pop() { alert("hello BOM!"); } function width() { alert("可用宽度: " + screen.availWidth); }</script> </html>
image