HTML面试记录
HTML5新特性
HTML5的语义化是指使用正确的HTML元素(标签)来清楚地描述其含义和结构,以便更好地传达网页的内容和结构。HTML5引入了多种新的语义元素,这些元素提供了比传统HTML更丰富的方式来描述网页的不同部分。语义化的HTML不仅可以提高网页的可读性,还有助于搜索引擎优化(SEO),并增强网页的可访问性。
HTML5是HTML的第五个版本,引入了许多新的特性和功能。以下是HTML5的一些新增的特性:
语义化标签:HTML5引入了一些新的语义化标签,如
header
、nav
、section
、article
等,使得网页结构更加清晰明了。视频和音频支持:HTML5提供了
video和
audio`标签,可以直接在网页中嵌入视频和音频内容,不再需要使用第三方插件。Canvas绘图:HTML5的
canvas
标签允许通过JavaScript在网页上绘制图形、动画和游戏等交互式内容。本地存储:HTML5引入了本地存储机制,包括
localStorage
和sessionStorage
,可以在浏览器端存储数据,提供了更好的离线应用支持。表单增强:HTML5为表单元素提供了一些新的属性和类型,如
input type="date"
、input type="email"
等,使得表单处理更加方便和灵活。地理定位:HTML5的地理定位API可以获取用户的地理位置信息,为基于位置的应用提供支持。
Web存储:HTML5提供了Web SQL Database和IndexedDB两种数据库存储方式,可以在浏览器端进行数据存储和查询。
Web Workers:HTML5的
Web Workers
允许在后台运行脚本,提高了网页的性能和响应能力。WebSocket:HTML5的
WebSocket
提供了全双工通信的能力,使得浏览器和服务器之间可以进行实时的双向通信。CSS3支持:虽然CSS3并非HTML5的一部分,但HTML5的出现推动了CSS3的发展,使得网页设计更加丰富多样。
script 标签中属性 async 和 defer 的区别?
script
会阻碍 HTML 解析,只有下载好并执行完脚本才会继续解析 HTMLasync script
:解析 HTML 的过程中会进行脚本的异步下载,下载成功后立马执行,因此有可能会阻断 HTML 的解析。多个脚本的执行顺序无法保证。defer script
:也是异步下载脚步,加载完成后,如果此时 HTML 还没有解析完,浏览器不会暂停解析去执行 JS 代码,而是等待 HTML 解析完毕再执行 JS 代码,如果存在多个defer script
标签,浏览器(IE9及以下除外)会保证它们按照在 HTML 中出现的顺序执行,不会破坏 JS 脚本之间的依赖关系。
建议阅读文章:图解 script 标签中的 async 和 defer 属性
src和href的区别
src
和href
都是用来加载外部资源,区别如下
src当浏览器解析到该元素时,会暂停其他资源的加载和处理,直到该资源加载完成。 它会将资源内容嵌入到当前标签所在的位置,将其指向的资源下载应用到文档内,如js
脚本等。常用在img
、script
、iframe
等标签。
href指向外部资源所在的位置,和当前元素位置建立链接,当浏览器解识别到它指向的位置,将其下载的时候不会阻止其他资源的加载解析。常用在a
、 link
标签。
DOCTYPE 的作用是什么?
!DOCTYE
声明一般位于文档的第一行,它的作用主要是告诉浏览器以什么样的模式来解析文档。一般指定了之后会以“标准模式”进行文档解析,否则就以“兼容模式”进行解析。
- 在
标准模式
下,浏览器的解析规则都是按照最新的标准进行解析的。 - 而在
兼容模式
下,浏览器会以向后兼容的方式来模拟老式浏览器的行为,以保证一些老的网站能正常访问。
SGML、HTML、XML 和 XHTML的区别
SGML
是标准通用标记语言,是一种定义电子文档结构和描述其内容的国际标准语言,是所有电子文档标记语言的起源。HTML
是超文本标记语言,主要是用于规定怎样显示网页。XML
是可扩展标记语言,是未来网页语言的发展方向,XML 和 HTML 的最大区别就在于 XML 的标签是可以自己创建的,数量无限多,而 HTML 的标签都是固定的而且数量有限。XHTML
也是现在基本上所有网页都在用的标记语言,他其实和 HTML 没什么本质的区别,标签都一样,用法也都一样,就是比 HTML 更严格,比如标签必须都用小写,标签都必须有闭合标签等。
对浏览器内核的理解
主要分为两部分:渲染引擎和JS引擎。
渲染引擎
:其职责就是渲染,即在浏览器窗口中显示所请求的内容。默认情况下,渲染引擎可以显示 HTML、 XML 文档及图片,它也可以借助一些浏览器扩展插件显示其他类型数据,如:使用PDF阅读器插件可以显示 PDF 格式。JS引擎
:解析和执行 JavaScript 来实现网页的动态效果。
最开始渲染引擎和JS引擎并没有区分的很明显,后来JS引擎越来越独立,内核就倾向于只指渲染引擎了。
什么是文档的预解析?
当执行 JavaScript 脚本时,另一个线程解析剩下的文档,并加载后面需要通过网络加载的资源。这种方式可以使资源并行加载,从而使整体速度更快。
需要注意的是,预解析并不改变DOM树,它将这个工作交给主解析过程,自己只解析外部资源的引用,比如:外部脚本、样式及图片。
浏览器的渲染原理
简记: 生成DOM树 –>生成CSS规则树
–>构建渲染树
–>布局
–> 绘制
- 首先解析收到的文档,根据文档定义构建一颗
DOM 树
,DOM 树是由 DOM 元素及属性节点组成的。 - 然后对 CSS 进行解析,生成一颗
CSS 规则树
。 - 根据 DOM 树和 CSS 规则树构建
渲染树
。渲染树的节点被称为渲染对象,它是一个包含有颜色等属性的矩形。渲染对象和 DOM 元素相对应,但这种关系不是一对一的,不可见的 DOM 元素不会插入渲染树。还有一些 DOM 元素对应几个可见对象,它们一般是一些具有复杂结构的元素,无法用一个矩形来描述。 - 当渲染对象被创建并添加到树中,它们没有位置和大小,所以当浏览器生成渲染树以后,就会根据渲染树来进行
布局
(也可以叫做回流)。这一阶段浏览器要做的是计算出各个节点在页面中确切位置和大小。通常这一行为也被称为自动重排。 - 布局阶段结束后是
绘制
阶段,遍历渲染树并调用渲染对象的 paint 方法将它们的内容显示到屏幕上。值得注意的是,这个过程是逐步完成的,为了更好的用户体验,渲染引擎会尽早的将内容呈现到屏幕上,并不会等到所有 HMTL 内容都解析完之后再去构建和布局渲染树,它是解析完一部分内容就显示一部分内容,同时,可能还通过网络下载其余内容。
什么是回流和重绘?
概念:
回流
:当 DOM 的变化影响了元素的几何信息,浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置,这个过程叫做回流(也可以叫做重排)。表现为重新生成布局,重新排列元素。重绘
:当一个元素的外观发生改变,重新把元素外观绘制出来的过程,叫做重绘。表现为某些元素的外观被改变。
常见引起回流和重绘的属性和方法:
任何会改变元素几何信息(元素的位置和尺寸大小)的操作都会触发回流。
- 添加或删除可见的 DOM 元素
- 元素尺寸改变–边距、填充、宽度、高度
- 浏览器尺寸改变– resize 事件发生时
- 计算 offsetWidth 和 offsetHeight 属性
- 设置 style 属性的值
- 修改网页默认字体
回流必定会发生重绘,重绘不一定会引发回流。
回流所需的成本比重绘高得多
如何减少回流?
- 使用 transform 代替 top
- 不要把节点的属性值放在一个循环里,当成循环里的变量
- 不要使用 table 布局,可能很小的一个改动会造成整个 table 的重新布局
- 把 DOM 离线后修改。如:使用 documentFragment 对象在内存里操作 DOM
- 不要一条一条的修改样式,可以预先定义好 class,然后修改 DOM 的 className
- 使用 absolute 或 fixed 使元素脱离文档流
sessionStorage,localStorage 和 cookie 的区别
- 共同点:都是保存在浏览器端,且同源的
- 区别:
- cookie 始终在同源的 http 请求中携带(即使不需要),即 cookie 在浏览器和服务器之间来回传递;而 sessionStorage 和 localStorage 不会自动把数据发送到服务器,仅在本地保存。cookie 还有路径(path)的概念,可以限制 cookie 只属于某个路径下。
- 存储大小限制不同。cookie 不能超过 4K,因为每次 http 请求都会携带 cookie,所以 cookie 只适合保存很小的数据,如:会话标识。sessionStorage 和 localStorage 虽然也有存储大小限制,但比 cookie 大得多,可以达到 5M 或更大。
- 数据有效期不同。sessionStorage 仅在当前浏览器窗口关闭之前有效;localStorage 始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie 只在设置的 cookie 过期时间之前有效。
- 作用域不同。sessionStorage 不在不同的浏览器窗口中共享,即使是同一个页面;localStorage 和 cookie 在所有同源窗口中都是共享的。
iframe 有哪些优缺点?
优点
iframe 能原封不动的把嵌入的网页展现出来。
如果有多个网页引用 iframe,只需修改 iframe 的内容,就可以实现调用每一个页面的更改,方便快捷。
内容隔离:
iframe
提供了一种将第三方内容隔离开来的方式,这在嵌入如视频、地图或第三方支付系统等内容时非常有用,因为它们在视觉上是页面的一部分,但在技术上则完全独立。安全性:通过
iframe
嵌入的内容运行在不同的上下文中,这有助于提升安全性,因为它限制了父页面与``iframe`内容之间的交互,减少了XSS攻击的风险。灵活性:
iframe
使得将其他网页的内容嵌入到当前页面变得简单,增加了网页设计的灵活性。第三方服务集成:方便集成如地图、视频、社交媒体分享或评论等第三方服务。
缺点
- 性能问题:每个
iframe
都是一个独立的网页,这意味着浏览器需要为每个iframe
元素执行额外的HTML、CSS和JavaScript解析。这可能会导致页面加载时间变长,特别是当嵌入多个iframe
时。 - 跨域:iframe 和主页面共享链接池,而浏览器对相同域的链接有限制,所以会影响页面的并行加载。默认情况下,
iframe
中的文档不能与其父文档交互,这是由同源策略限制的。虽然可以通过某些技术(如窗口消息传递)绕过这一限制,但这增加了开发的复杂度。 - SEO:代码复杂,无法一下被搜索引擎索引到。搜索引擎可能不会抓取
iframe
中的内容,这意味着嵌入的内容对于提升网站的搜索引擎排名没有帮助。 - iframe 框架页面会增加服务器的 http 请求,对于大型网站不可取。
- 移动设备的兼容性
注意:通过动态给 iframe 添加 src 属性值,可解决前两个问题。
什么是 canvas,基本用法是什么?
canvas 元素是 HTML5 的一部分,允许脚步语言动态渲染位图像。canvas 由一个可控制区域 HTML 代码中的属性定义决定高度和宽度。JavaScript 代码可以访问该区域,通过一套完整的绘图功能类似于其他通用二维的 API,从而生成动态的图形。
创建 canvas 标签
1 | `canvas id="myCanvas" width="150" height="150"`该浏览器不支持canvas`/canvas` |
渲染上下文
1 | var canvas = document.getElementById('myCanvas'); |
代码第一行通过使用 document.getElementById()
方法获取 canvas
元素对应的 DOM 对象,然后可以通过使用它的 getContext()
方法来绘制上下文。 创建 canvas 标签时可以在标签内写上不支持的提示信息;也可以通过 getContext()
方法判读是否支持编程。
1 | var canvas = document.getElementById('myCanvas'); |
用途:
canvas 可用于游戏和图表(echarts.js、heightchart.js 都是基于 canvas 来绘图)制作。
web workers如何与主线程进行通信?
Web Worker
是运行在后台的 JavaScript 代码,可以在独立的线程中执行,不会阻塞主线程。与主线程通信是一种必须的机制,允许主线程与 Web Worker 之间传递数据和消息。
通信方式主要有两种:
- 使用消息传递 API:这是最常见的方式,它使用
postMessage()
和onmessage
来进行通信。主线程和 Web Worker 都可以通过postMessage()
方法向对方发送消息,并通过在相应对象上设置onmessage
事件来接收消息。这种方式是异步的。
在主线程中发送消息给 Web Worker:
1 | const worker = new Worker('worker.js'); |
在 Web Worker 中接收消息并回复:
1 | self.onmessage = function(event) { |
- 共享数据:Web Worker 可以访问一些与主线程共享的数据结构,例如
SharedArrayBuffer
和Atomics
对象。这些对象允许主线程和 Web Worker 之间在特定内存区域共享数据,并且可以在不同线程之间同步访问。
1 | // 在主线程中创建共享内存 |
需要注意的是,在使用共享内存时要格外小心,因为共享内存可以引起竞态条件和数据不一致的问题。
websocket
HTML5 引入了 WebSocket,它是一种全双工、双向通信的协议,旨在通过单个持久连接在客户端和服务器之间实现实时数据传输。这与传统的 HTTP 请求-响应模型不同,WebSocket 允许服务器和客户端在建立连接后,彼此之间自由地发送数据,而不需要客户端每次请求后等待服务器响应,特别适用于即时通讯、实时更新、在线游戏等需要快速数据交互的场景。
WebSocket 的特点
双向通信:一旦 WebSocket 连接建立后,客户端和服务器可以相互发送消息,而不需要像 HTTP 那样,客户端发送请求,服务器响应数据。这使得 WebSocket 非常适合实时应用。
持久连接:WebSocket 建立连接后,连接是持久的,不像 HTTP 的短连接每次请求后都需要重新连接。这种特性大大减少了重复连接的开销。
低延迟:由于 WebSocket 持续保持连接,客户端与服务器可以快速交换数据,无需经历 HTTP 的请求/响应周期,极大降低了延迟,适用于需要低延迟的应用场景。
轻量级协议:WebSocket 协议设计简洁,消息头的开销非常小,适合频繁交换少量数据的场景(如在线聊天、实时更新的游戏、股票行情等)。
WebSocket 和 HTTP 的区别
- 通信模式:HTTP 是单向的请求-响应模式,而 WebSocket 是双向的。
- 连接方式:HTTP 是短连接,连接在每次请求后关闭,而 WebSocket 是持久连接,一旦建立连接就会保持活跃。
- 数据传输:HTTP 在每次传输时都需要传输较大的请求头和响应头,而 WebSocket 在初始握手之后,数据传输时仅包含最小的头信息。
WebSocket 的工作流程
建立连接:客户端使用 HTTP 请求和服务器进行握手,升级协议为 WebSocket。在握手成功后,HTTP 连接升级为 WebSocket 连接。
WebSocket 使用的是标准的 HTTP 协议端口(80 或 443),并通过
ws://
或wss://
来指定使用 WebSocket 协议。数据交换:一旦连接建立,客户端和服务器可以通过该连接发送和接收消息。此时数据通过 WebSocket 的帧格式发送,效率更高。
关闭连接:当通信结束时,客户端或服务器可以关闭连接,释放资源。
WebSocket 的应用场景
WebSocket 非常适合需要实时数据更新的场景,常见的应用有:
- 即时通讯应用:如在线聊天、消息推送等,需要保持双向通信。
- 实时数据更新:如股票市场价格、体育赛事比分等需要低延迟更新的场景。
- 在线游戏:特别是多人在线游戏,数据需要频繁在服务器和客户端之间来回传输。
- 协同编辑:如 Google Docs 这类的实时协作工具,需要快速同步各用户的操作。
- **物联网 (IoT)**:WebSocket 也被广泛应用于 IoT 设备与服务器的通信中,实现低延迟的数据传输和状态更新。
WebSocket 基本使用
WebSocket API 在浏览器中非常简单,可以通过 JavaScript 创建并与服务器进行通信。
客户端代码示例
1 | // 创建 WebSocket 连接 |
WebSocket 与 HTTP 长轮询的比较
在 WebSocket 出现之前,通常使用 长轮询 来模拟实时通信。长轮询是一种客户端持续向服务器发起 HTTP 请求,询问是否有新数据的方式。虽然能实现一定程度的实时通信,但有以下缺点:
- 效率低:长轮询需要客户端不断发起 HTTP 请求,即使没有数据也会浪费资源。
- 高延迟:因为需要每隔一段时间发起请求,不能做到实时更新。
- 服务器压力大:大量的无效请求给服务器带来了不小的负担。
WebSocket 完全解决了这些问题,它只需建立一次连接,然后保持这个连接,可以即时双向传输数据,大大提高了效率。