前端试题及答案

来自javascript

HTML

DOCTYPE 的做用是什么?

DOCTYPE通常位于文档的第一行,它告诉浏览器以什么样的格式来解析文档,通常指定了以后会以标准模式来进行文档解析,不然就以兼容模式进行解析。在标准模式下,浏览器的解析规则都是按照最新的标准进行解析的。而在兼容模式下,浏览器会以向后兼容的方式来模拟老式浏览器的行为,以保证一些老的网站的正确访问。

在 html5 以后再也不须要指定 DTD 文档,由于 html5 之前的 html 文档都是基于 SGML 的,因此须要经过指定 DTD 来定义文档中容许的属性以及一些规则。而 html5 再也不基于 SGML 了,因此再也不须要使用 DTD。css

在HTML中,文档类型声明是必要的。全部的文档的头部,你都将会看到" <!DOCTYPE html>" 的身影。这个声明的目的是防止浏览器在渲染文档时,切换到咱们称为“ 怪异模式(兼容模式)”的渲染模式。“ <!DOCTYPE html>" 确保浏览器按照最佳的相关规范进行渲染,而不是使用一个不符合规范的渲染模式。——MDN解释

标准模式和兼容模式有什么区别?

标准模式的渲染方式和JS引擎的解析方式都是以该浏览器支持的的最高标准运行。兼容模式中,页面以宽松向后兼容的方式显示,模拟老式浏览器的行为以防止站点没法工做。html

行内元素和块级元素以及他们的区别

一个行内元素只占据它对应标签的边框所包含的空间。

常见的行内元素有 a b span img strong sub sup button input label select textarea前端

块级元素占据其父元素(容器)的整个宽度,所以建立了一个“块”。

常见的块级元素有 div ul ol li dl dt dd h1 h2 h3 h4 h5 h6 p
区别vue

(1) 格式上,默认状况下,行内元素不会以新行开始,而块级元素会新起一行。
(2) 内容上,默认状况下,行内元素只能包含文本和其余行内元素。而块级元素能够包含行内元素和其余块级元素。
(3) 行内元素与块级元素属性的不一样,主要是盒模型属性上:行内元素设置 width 无效,height 无效(能够设置 line-height),设置 margin 和 padding 的上下不会对其余元素产生影响。

HTML5 元素的分类

HTML4中,元素被分红两大类: inline(内联元素)与 block(块级元素)。但在实际的开发过程当中,由于页面表现的须要,前端工程师常常把 inline 元素的 display 值设定为 block (好比 a 标签),也常常把 block 元素的 display 值设定为 inline 以后更是出现了 inline-block 这一对外呈现 inline 对内呈现 block 的属性。所以,简单地把 HTML 元素划分为 inline 与 block 已经再也不符合实际需求。

HTML5中,元素主要分为7类:Metadata Flow Sectioning Heading Phrasing Embedded Interactivehtml5

空元素定义

标签内没有内容的 HTML 标签被称为空元素。空元素是在开始标签中关闭的。

常见的空元素有:br hr img input link metajava

link 标签订义

link 标签订义文档与外部资源的关系。

link 元素是空元素,它仅包含属性。 此元素只能存在于 head 部分,不过它可出现任何次数。react

link 标签中的 rel 属性定义了当前文档与被连接文档之间的关系。常见的 stylesheet 指的是定义一个外部加载的样式表。css3

页面导入样式时,使用 link 和 @import 有什么区别?

(1)从属关系区别。 @import 是 CSS 提供的语法规则,只有导入样式表的做用;link 是 HTML 提供的标签,不只能够加载 CSS 文件,还能够定义 RSS、rel 链接属性、引入网站图标等。

(2)加载顺序区别。加载页面时,link 标签引入的 CSS 被同时加载;@import 引入的 CSS 将在页面加载完毕后被加载。git

(3)兼容性区别。@import 是 CSS2.1 才有的语法,故只可在 IE5+ 才能识别;link 标签做为 HTML 元素,不存在兼容性问题。

(4)DOM 可控性区别。能够经过 JS 操做 DOM ,插入 link 标签来改变样式;因为 DOM 方法是基于文档的,没法使用 @import 的方式插入样式。

你对浏览器的理解

浏览器的主要功能是将用户选择的 web 资源呈现出来,它须要从服务器请求资源,并将其显示在浏览器窗口中,资源的格式一般是 HTML,也包括 PDF、image 及其余格式。用户用 URI(Uniform Resource Identifier 统一资源标识符)来指定所请求资源的位置。

URI(统一资源标识符)是一个指向资源的字符串。最一般用在 URL上来指定Web上资源文件的具体位置。相比之下,URN是在给定的命名空间用名字指向具体的资源,如:书本的ISBN。
HTML 和 CSS 规范中规定了浏览器解释 html 文档的方式,由 W3C 组织对这些规范进行维护,W3C 是负责制定 web 标准的
组织。

可是浏览器厂商纷纷开发本身的扩展,对规范的遵循并不完善,这为 web 开发者带来了严重的兼容性问题。

简单来讲浏览器能够分为两部分,shell 和 内核。

其中 shell 的种类相对比较多,内核则比较少。shell 是指浏览器的外壳:例如菜单,工具栏等。主要是提供给用户界面操做,参数设置等等。它是调用内核来实现各类功能的。内核才是浏览器的核心。内核是基于标记语言显示内容的程序或模块。

介绍一下你对浏览器内核的理解?

主要分红两部分:渲染引擎和 JS 引擎。
渲染引擎的职责就是渲染,即在浏览器窗口中显示所请求的内容。默认状况下,渲染引擎能够显示 html、xml 文档及图片,它也能够借助插件(一种浏览器扩展)显示其余类型数据,例如使用 PDF 阅读器插件,能够显示 PDF 格式。
JS 引擎:解析和执行 javascript 来实现网页的动态效果。

最开始渲染引擎和 JS 引擎并无区分的很明确,后来 JS 引擎愈来愈独立,内核就倾向于只指渲染引擎。

浏览器的渲染原理?

(1)首先解析收到的文档,根据文档定义构建一棵 DOM 树,DOM 树是由 DOM 元素及属性节点组成的。
(2)而后对 CSS 进行解析,生成 CSSOM 规则树。
(3)根据 DOM 树和 CSSOM 规则树构建渲染树。渲染树的节点被称为渲染对象,渲染对象是一个包含有颜色和大小等属性的矩形,渲染对象和 DOM 元素相对应,但这种对应关系不是一对一的,不可见的 DOM 元素不会被插入渲染树。还有一些 DOM 元素对应几个可见对象,它们通常是一些具备复杂结构的元素,没法用一个矩形来描述。
(4)当渲染对象被建立并添加到树中,它们并无位置和大小,因此当浏览器生成渲染树之后,就会根据渲染树来进行布局(也能够叫作 回流)。这一阶段浏览器要作的事情是要弄清楚各个节点在页面中的确切位置和大小。一般这一行为也被称为“自动重排”。
(5)布局阶段结束后是绘制阶段,遍历渲染树并调用渲染对象的 paint 方法将它们的内容显示在屏幕上,绘制使用 UI 基础组件。

值得注意的是,这个过程是逐步完成的,为了更好的用户体验,渲染引擎将会尽量早的将内容呈现到屏幕上,并不会等到全部的html 都解析完成以后再去构建和布局 render 树。它是解析完一部份内容就显示一部份内容,同时,可能还在经过网络下载其他内容。

渲染过程当中遇到 JS 文件怎么处理?(浏览器解析过程)

JavaScript 的加载、解析与执行会阻塞文档的解析,也就是说,在构建 DOM 时,HTML 解析器若遇到了 JavaScript,那么它会暂停文档的解析,将控制权移交给 JavaScript 引擎,等 JavaScript 引擎运行完毕,浏览器再从中断的地方恢复继续解析文档。

也就是说,若是你想首屏渲染的越快,就越不该该在首屏就加载 JS 文件,这也是都建议将 script 标签放在 body 标签底部的缘由。固然在当下,并非说 script 标签必须放在底部,由于你能够给 script 标签添加 defer 或者 async 属性。

async 和 defer 的做用是什么?有什么区别?(浏览器解析过程)

(1)脚本没有 defer 或 async,浏览器会当即加载并执行指定的脚本,也就是说不等待后续载入的文档元素,读到就加载并执行。
(2)defer(推迟) 属性表示延迟执行引入的 JavaScript,即这段 JavaScript 加载时 HTML 并未中止解析,这两个过程是并行的。当整个 document 解析完毕后再执行脚本文件,在 DOMContentLoaded 事件触发以前完成。多个脚本按顺序执行。
(3)async 属性表示异步执行引入的 JavaScript,与 defer 的区别在于,若是已经加载好,就会开始执行,也就是说它的执行仍然会阻塞文档的解析,只是它的加载过程不会阻塞。多个脚本的执行顺序没法保证。

什么是文档的预解析?(浏览器解析过程)

Webkit和Firefox都作了这个优化,当执行JavaScript脚本时,另外一个线程解析剩下的文档,并加载后面须要经过网络加载的资源。这种方式可使资源并行加载从而使总体速度更快。须要注意的是,预解析并不改变DOM树,它将这个工做留给主解析过程,本身只解析外部资源的引用,好比外部脚本、样式表及图片。

CSS如何阻塞文档解析?(浏览器解析过程)

理论上,既然样式表不改变 DOM 树,也就没有必要停下文档的解析等待它们,然而,存在一个问题,JavaScript 脚本执行时可能在文档的解析过程当中请求样式信息,若是样式尚未加载和解析,脚本将获得错误的值,显然这将会致使不少问题。

若是浏览器还没有完成 CSSOM 的下载和构建,而咱们却想在此时运行脚本,那么浏览器将延迟 JavaScript 脚本执行和文档的解析,直至其完成 CSSOM 的下载和构建。也就是说,在这种状况下,浏览器会先下载和构建 CSSOM,而后再执行 JavaScript,最后再继续文档的解析。

渲染页面时常见哪些不良现象?(浏览器渲染过程)

FOUC:
主要指的是样式闪烁的问题,因为浏览器渲染机制(好比Firefox),在CSS加载以前,先呈现了HTML,就会致使展现出现无样式内容,而后样式忽然呈现的现象。会出现这个问题的缘由主要是CSS加载时间过长,或者CSS被放在了文档底部。

白屏:
有些浏览器渲染机制(好比chrome)要先构建 DOM 树和CSSOM 树,构建完成后再进行渲染,若是 CSS 部分放在 HTML 尾部,因为CSS 未加载完成,浏览器迟迟未渲染,从而致使白屏;也多是把 js文件放在头部,脚本的加载会阻塞后面文档内容的解析,从而页面迟迟未渲染出来,出现白屏问题。

如何优化关键渲染路径?(浏览器渲染过程)

为尽快完成首次渲染,咱们须要最大限度减少如下三种可变因素:
(1)关键资源的数量。
(2)关键路径长度。
(3)关键字节的数量。

关键资源是可能阻止网页首次渲染的资源。这些资源越少,浏览器的工做量就越小,对 CPU 以及其余资源的占用也就越少。
一样,关键路径长度受全部关键资源与其字节大小之间依赖关系图的影响:某些资源只能在上一资源处理完毕以后才能开始下载,而且资源越大,下载所需的往返次数就越多。
最后,浏览器须要下载的关键字节越少,处理内容并让其出如今屏幕上的速度就越快。要减小字节数,咱们能够减小资源数(将它们删除或设为非关键资源),此外还要压缩和优化各项资源,确保最大限度减少传送大小。

优化关键渲染路径的常规步骤以下:
(1)对关键路径进行分析和特性描述:资源数、字节数、长度。
(2)最大限度减小关键资源的数量:删除它们,延迟它们的下载,将它们标记为异步等。
(3)优化关键字节数以缩短下载时间(往返次数)。
(4)优化其他关键资源的加载顺序:您须要尽早下载全部关键资产,以缩短关键路径长度。

什么是重绘和回流?(浏览器绘制过程)

重绘:
当渲染树中的一些元素须要更新属性,而这些属性只是影响元素的外观、风格,而不会影响布局的操做,好比 background-color,咱们将这样的操做称为重绘。
回流:
当渲染树中的一部分(或所有)由于元素的规模尺寸、布局、隐藏等改变而须要从新构建的操做,会影响到布局的操做,这样的操做咱们称为回流。

任何会改变元素几何信息(元素的位置和尺寸大小)的操做,都会触发回流。
会致使回流的操做:

  • 页面首次渲染
  • 添加或者删除可见的 DOM 元素;
  • 元素尺寸改变——边距、填充、边框、宽度和高度
  • 内容变化,好比用户在 input 框中输入文字
  • 浏览器窗口尺寸改变——resize事件发生时
  • 计算 offsetWidthoffsetHeight 属性
  • 设置 style 属性的值
  • 当你修改网页的默认字体,或者字体大小变化
  • 激活CSS伪类(例如: :hover

一些经常使用致使回流的方法:

  • clientWidthclientHeightclientTopclientLeft
  • offsetWidthoffsetHeightoffsetTopoffsetLeft
  • scrollWidthscrollHeightscrollTopscrollLeft
  • scrollIntoView()scrollIntoViewIfNeeded()
  • getComputedStyle()
  • getBoundingClientRect()
  • scrollTo()

回流一定会发生重绘,重绘不必定会引起回流。回流所需的成本比重绘高的多,改变父节点里的子节点极可能会致使父节点的一系列回流。

回流比重绘的代价要更高。
有时即便仅仅回流一个单一的元素,它的父元素以及任何跟随它的元素也会产生回流。
现代浏览器会对频繁的回流或重绘操做进行优化:

浏览器会维护一个队列,把全部引发回流和重绘的操做放入队列中,若是队列中的任务数量或者时间间隔达到一个阈值的,浏览器就会将队列清空,进行一次批处理,这样能够把屡次回流和重绘变成一次。

当你访问如下属性或方法时,浏览器会马上清空队列:

  • clientWidthclientHeightclientTopclientLeft
  • offsetWidthoffsetHeightoffsetTopoffsetLeft
  • scrollWidthscrollHeightscrollTopscrollLeft
  • widthheight
  • getComputedStyle()
  • getBoundingClientRect()

由于队列中可能会有影响到这些属性或方法返回值的操做,即便你但愿获取的信息与队列中操做引起的改变无关,浏览器也会强行清空队列,确保你拿到的值是最精确的。

如何减小回流?(浏览器绘制过程)

  • 放弃传统操做 DOM 的时代,基于 vue/react 开始数据影响视图模式,mvvm / mvc / virtual dom / dom diff ......vue / react
数据驱动思想 :
咱们本身不操做DOM,咱们只操做数据,让框架帮咱们根据数据渲染视图(框架内部自己对于DOM的回流和重绘以及其它性能优化作的很是好)
  • 分离读写操做(现代浏览器的渲染队列的机制)(重要)
遇到一行修改样式的代码,先放到渲染队列中,继续看 下面一行代码 是否还为修改样式的,若是是继续增长到渲染队列中...直到下面的代码再也不是修改样式的,而是获取样式的代码!此时再也不向渲染队列中增长,把以前渲染队列中要修改的样式一次性渲染到页面中,引起一次DOM的回流和重绘。
  • 元素批量修改(重要)
DOM的增长也会引发回流重绘
文档碎片:临时建立的一个存放文档的容器,咱们能够把新建立的LI,存放到容器中,当全部的LI都存储完,咱们统一把容器中的内容增长到页面中(只触发一次回流)
字符串拼接:项目中,有一个文档碎片相似的方式,也是把要建立的LI事先存储好,最后统一放到页面中渲染(字符串拼接)
不要把节点的属性值放在一个循环里当成循环里的变量
  • 动画效果应用到 position 属性为 absolutefixed 的元素上(脱离文档流)
也会引发回流重绘,只不过重新计算过程当中,由于他脱离文档流了,不会对其余元素产生影响,从新计算的过程当中比较快一点。
  • 不要使用 table 布局,可能很小的一个小改动会形成整个 table 的从新布局

为何操做 DOM 慢?(浏览器绘制过程)

一些 DOM 的操做或者属性访问可能会引发页面的回流和重绘,从而引发性能上的消耗。

DOMContentLoaded 事件和 Load 事件的区别?

当初始的 HTML 文档被彻底加载和解析完成以后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的加载完成。
Load 事件是当全部资源加载完成后触发的。

结合DOM文档加载的加载步骤,DOMContentLoaded事件/Load事件,触发时机以下:

一、解析HTML结构。  
二、加载外部脚本和样式表文件。  
三、解析并执行脚本代码。// 部分脚本会阻塞页面的加载  
四、DOM树构建完成。//DOMContentLoaded 事件  
五、加载图片等外部文件。  
六、页面加载完毕。//load 事件

在第4步会触发DOMContentLoading事件,第6步触发load事件
原生js写法:

// 不兼容老的浏览器,兼容写法见[jQuery中ready与load事件]
document.addEventListener("DOMContentLoaded", function() {
   // ...代码...
}, false);

window.addEventListener("load", function() {
    // ...代码...
}, false);

jQuery写法:

// DOMContentLoaded
$(document).ready(function() {
    // ...代码...
});

//load
$(document).load(function() {
    // ...代码...
});

HTML5 有哪些新特性、移除了那些元素?

HTML5 如今已经不是 SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增长。

 新增的有:
  
 绘画 canvas;
 用于媒介回放的 video 和 audio 元素;
 本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失;
 sessionStorage 的数据在浏览器关闭后自动删除;
 语意化更好的内容元素,好比 article、footer、header、nav、section;
 表单控件,calendar、date、time、email、url、search;
 新的技术 webworker, websocket;
 新的文档属性 document.visibilityState

 移除的元素有:

 纯表现的元素:basefont,big,center,font, s,strike,tt,u;
 对可用性产生负面影响的元素:frame,frameset,noframes;

如何处理 HTML5 新标签的浏览器兼容问题?

1) IE8/IE7/IE6 支持经过 document.createElement 方法产生的标签,能够利用这一特性让这些浏览器
支持 HTML5 新标签,浏览器支持新标签后,还须要添加标签默认的样式。

(2) 固然也能够直接使用成熟的框架,好比 html5shim ;

`<!--[if lt IE 9]>
  <script> src="http://html5shim.googlecode.com/svn/trunk/html5.js"</script>
  <![endif]-->`

  [if lte IE 9]……[endif] 判断 IE 的版本,限定只有 IE9 如下浏览器版本须要执行的语句。

简述一下你对 HTML 语义化的理解?

(1) 用正确的标签作正确的事情。
 (2) html 语义化让页面的内容结构化,结构更清晰,便于对浏览器、搜索引擎解析;
 (3) 即便在没有样式 CSS 状况下也以一种文档格式显示,而且是容易阅读的;
 (4) 搜索引擎的爬虫也依赖于 HTML 标记来肯定上下文和各个关键字的权重,利于 SEO ;
 (5) 使阅读源代码的人对网站更容易将网站分块,便于阅读维护理解。
我认为 html 语义化主要指的是咱们应该使用合适的标签来划分网页内容的结构。html 的本质做用其实就是定义网页文档的结构,一个语义化的文档,可以使页面的结构更加清晰,易于理解。这样不只有利于开发者的维护和理解,同时也可以使机器对文档内容进行正确的解读。好比说咱们经常使用的 b 标签和 strong 标签,它们在样式上都是文字的加粗,可是 strong 标签拥有强调的语义。
对于通常显示来讲,可能咱们看上去没有差别,可是对于机器来讲,就会有很大的不一样。若是用户使用的是屏幕阅读器来访问网页的话,使用 strong 标签就会有明显的语调上的变化,而 b 标签则没有。若是是搜索引擎的爬虫对咱们网页进行分析的话,那么它会依赖于 html 标签来肯定上下文和各个关键字的权重,一个语义化的文档对爬虫来讲是友好的,是有利于爬虫对文档内容解读的,从而有利于咱们网站的 SEO 。从 html5 咱们能够看出,标准是倾向于以语义化的方式来构建网页的,好比新增了 header 、footer 这些语义标签,删除了 big 、font 这些没有语义的标签。

更多

b 与 strong 的区别和 i 与 em 的区别?

从页面显示效果来看,被 <b><strong> 包围的文字将会被加粗,而被 <i><em> 包围的文字将以斜体的形式呈现。
可是 <b> <i> 是天然样式标签,分别表示无心义的加粗,无心义的斜体,表现样式为 { font-weight: bolder},仅仅表示「这里应该用粗体显示」或者「这里应该用斜体显示」,此两个标签在 HTML4.01 中并不被推荐使用。
<em><strong> 是语义样式标签。 <em> 表示通常的强调文本,而 <strong> 表示比 <em> 语义更强的强调文本。
使用阅读设备阅读网页时: <strong> 会重读,而 <b> 是展现强调内容。

前端须要注意哪些 SEO ?

(1)合理的 title、description、keywords:搜索对着三项的权重逐个减少,title 值强调重点便可,重要关键词出现不要超过2次,并且要靠前,不一样页面 title 要有所不一样;description 把页面内容高度归纳,长度合适,不可过度堆砌关键词,不一样页面 description 有所不一样;keywords 列举出重要关键词便可。

 (2)语义化的 HTML 代码,符合 W3C 规范:语义化代码让搜索引擎容易理解网页。

 (3)重要内容 HTML 代码放在最前:搜索引擎抓取 HTML 顺序是从上到下,有的搜索引擎对抓取长度有限制,保证重要内容确定被
     抓取。

 (4)重要内容不要用 js 输出:爬虫不会执行 js 获取内容

 (5)少用 iframe:搜索引擎不会抓取 iframe 中的内容

 (6)非装饰性图片必须加 alt

 (7)提升网站速度:网站速度是搜索引擎排序的一个重要指标

HTML5 的离线储存怎么使用,工做原理能不能解释一下?

在用户没有与因特网链接时,能够正常访问站点或应用,在用户与因特网链接时,更新用户机器上的缓存文件。

原理:HTML5 的离线存储是基于一个新建的 .appcache 文件的缓存机制(不是存储技术),经过这个文件上的解析清单离线存储资源,这些资源就会像 cookie 同样被存储了下来。以后当网络在处于离线状态下时,浏览器会经过被离线存储的数据进行页面展现。

如何使用:

 (1)建立一个和 html 同名的 manifest 文件,而后在页面头部像下面同样加入一个 manifest 的属性。

     <html lang="en" manifest="index.manifest">

 (2)在以下 cache.manifest 文件的编写离线存储的资源。
       CACHE MANIFEST
       #v0.11
       CACHE:
       js/app.js
       css/style.css
       NETWORK:
       resourse/logo.png
       FALLBACK:
       / /offline.html
CACHE: 表示须要离线存储的资源列表,因为包含 manifest 文件的页面将被自动离线存储,因此不须要把页面自身也列出来。
 NETWORK: 表示在它下面列出来的资源只有在在线的状况下才能访问,他们不会被离线存储,因此在离线状况下没法使用这些资源。不过,若是在 CACHE 和 NETWORK 中有一个相同的资源,那么这个资源仍是会被离线存储,也就是说 CACHE 的优先级更高。
 FALLBACK: 表示若是访问第一个资源失败,那么就使用第二个资源来替换他,好比上面这个文件表示的就是若是访问根目录下任何一个资源失败了,那么就去访问 offline.html 。

在离线状态时,操做 window.applicationCache 进行离线缓存的操做。

如何更新缓存:

(1)更新 manifest 文件
(2)经过 javascript 操做
(3)清除浏览器缓存

注意事项:

(1)浏览器对缓存数据的容量限制可能不太同样(某些浏览器设置的限制是每一个站点 5MB)。
(2)若是 manifest 文件,或者内部列举的某一个文件不能正常下载,整个更新过程都将失败,浏览器继续所有使用老的缓存。
(3)引用 manifest 的 html 必须与 manifest 文件同源,在同一个域下。
(4)FALLBACK 中的资源必须和 manifest 文件同源。
(5)当一个资源被缓存后,该浏览器直接请求这个绝对路径也会访问缓存中的资源。
(6)站点中的其余页面即便没有设置 manifest 属性,请求的资源若是在缓存中也从缓存中访问。
(7)当 manifest 文件发生改变时,资源请求自己也会触发更新。

浏览器是怎么对 HTML5 的离线储存资源进行管理和加载的呢?

在线的状况下,浏览器发现 html 头部有 manifest 属性,它会请求 manifest 文件,若是是第一次访问 app ,那么浏览器就会根据 manifest 文件的内容下载相应的资源而且进行离线存储。若是已经访问过 app 而且资源已经离线存储了,那么浏览器就会使用离线的资源加载页面,而后浏览器会对比新的 manifest 文件与旧的 manifest 文件,若是文件没有发生改变,就不作 任何操做,若是文件改变了,那么就会从新下载文件中的资源并进行离线存储。
离线的状况下,浏览器就直接使用离线存储的资源。
~~

常见的浏览器端的存储技术有哪些?

浏览器常见的存储技术有 cookie、localStorage 和 sessionStorage。
还有两种存储技术用于大规模数据存储,webSQL(已被废除)和 indexDB。
IE 支持 userData 存储数据,可是基本不多使用到,除非有很强的浏览器兼容需求。

cookie的基本通讯流程:设置cookie=>cookie被自动添加到request header中 => 服务端接收到cookie
关于cookie

请描述一下 cookies,sessionStorage 和 localStorage 的区别?

SessionStorage, LocalStorage, Cookie 这三者均可以被用来在浏览器端存储数据,并且都是字符串类型的键值对。区别在于前二者属于 HTML5 WebStorage,建立它们的目的便于客户端存储数据。而 cookie 是网站为了标示用户身份而储存在用户本地终端上的数据(一般通过加密)。cookie 数据始终在同源(协议、主机、端口相同)的 http 请求中携带(即便不须要),会在浏览器和服务器间来回传递。

  • 存储大小:

    cookie 数据大小不能超过4 k 。
    sessionStorage 和 localStorage 虽然也有存储大小的限制,但比 cookie 大得多,能够达到 5M 或更大。

  • 有期时间:

    localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据。
    sessionStorage 数据在页面会话结束时会被清除。页面会话在浏览器打开期间一直保持,而且从新加载或恢复页面仍会保持原来的页面会话。在新标签或窗口打开一个页面时会在顶级浏览上下文中初始化一个新的会话。
    cookie设置的 cookie 过时时间以前一直有效,即便窗口或浏览器关闭。

  • 做用域:

    sessionStorage 只在同源的同学口(或标签页)中共享数据,也就是只在当前会话中共享。
    localStorage 在全部同源窗口中都是共享的。
    cookie 在全部同源窗口中都是共享的。

浏览器端经常使用的存储技术是 cookielocalStoragesessionStorage

cookie 其实最开始是服务器端用于记录用户状态的一种方式,由服务器设置,在客户端存储,而后每次发起同源请求时,发送给服务器端。cookie 最多能存储 4 k 数据,它的生存时间由 expires 属性指定,而且 cookie 只能被同源的页面访问共享。

sessionStorage 是 html5 提供的一种浏览器本地存储的方法,它借鉴了服务器端 session 的概念,表明的是一次会话中所保存的数据。它通常可以存储 5M 或者更大的数据,它在当前窗口关闭后就失效了,而且 sessionStorage 只能被同一个窗口的同源页面所访问共享。

localStorage 也是 html5 提供的一种浏览器本地存储的方法,它通常也可以存储 5M 或者更大的数据。它和 sessionStorage不一样的是,除非手动删除它,不然它不会失效,而且localStorage 也只能被同源页面所访问共享。

上面几种方式都是存储少许数据的时候的存储方式,当咱们须要在本地存储大量数据的时候,咱们可使用浏览器的 indexDB 这是浏览器提供的一种本地的数据库存储机制。它不是关系型数据库,它内部采用对象仓库的形式存储数据,它更接近 NoSQL 数据库。

indexDB

Label 的做用是什么?是怎么用的?

label 标签来定义表单控制间的关系,当用户选择该标签时,浏览器会自动将焦点转到和标签相关的表单控件上。

 <label for="Name">Number:</label>
 <input type=“text“ name="Name" id="Name"/>

HTML5 的 form 的自动完成功能是什么?

autocomplete 属性规定输入字段是否应该启用自动完成功能。默认为启用,设置为 autocomplete=off 能够关闭该功能。
自动完成容许浏览器预测对字段的输入。当用户在字段开始键入时,浏览器基于以前键入过的值,应该显示出在字段中填写的选项。
autocomplete 属性适用于 <form>,以及下面的 <input> 类型:text, search, url, telephone, email, password, datepickers, range 以及 color。

如何实现浏览器内多个标签页之间的通讯?

(1)使用 WebSocket,通讯的标签页链接同一个服务器,发送消息到服务器后,服务器推送消息给全部链接的客户端。

(2)使用 SharedWorker (只在 chrome 浏览器实现了),两个页面共享同一个线程,经过向线程发送数据和接收数据来实现标签页之间的双向通行。

(3)能够调用 localStorage、cookies 等本地存储方式,localStorge 另外一个浏览上下文里被添加、修改或删除时,它都会触发一个 storage 事件,咱们经过监听 storage 事件,控制它的值来进行页面信息通讯;

(4)若是咱们可以得到对应标签页的引用,经过 postMessage 方法也是能够实现多个标签页通讯的。

实现多个标签页之间的通讯,本质上都是经过中介者模式来实现的。由于标签页之间没有办法直接通讯,所以咱们能够找一个中介者,
让标签页和中介者进行通讯,而后让这个中介者来进行消息的转发。

第一种实现的方式是使用 websocket 协议,由于 websocket 协议能够实现服务器推送,因此服务器就能够用来当作这个中介者。
标签页经过向服务器发送数据,而后由服务器向其余标签页推送转发。

第二种是使用 ShareWorker 的方式,shareWorker 会在页面存在的生命周期内建立一个惟一的线程,而且开启多个页面也只会使
用同一个线程。这个时候共享线程就能够充当中介者的角色。标签页间经过共享一个线程,而后经过这个共享的线程来实现数据的交
换。

第三种方式是使用 localStorage 的方式,咱们能够在一个标签页对 localStorage 的变化事件进行监听,而后当另外一个标签页
修改数据的时候,咱们就能够经过这个监听事件来获取到数据。这个时候 localStorage 对象就是充当的中介者的角色。

还有一种方式是使用 postMessage 方法,若是咱们可以得到对应标签页的引用,咱们就可使用 postMessage 方法,进行通讯。

websocket

什么是WebSocket?

HTML5开始提供的一种浏览器与服务器进行全双工通信的网络技术,属于应用层协议。它基于TCP传输协议,并复用HTTP的握手通道。
其实只要记住几点:

  1. WebSocket能够在浏览器里使用
  2. 支持双向通讯
  3. 使用很简单
WebSocket优势

说到优势,这里的对比参照物是HTTP协议,归纳地说就是:支持双向通讯,更灵活,更高效,可扩展性更好。

  1. 支持双向通讯,实时性更强。
  2. 更好的二进制支持。
  3. 较少的控制开销。链接建立后,ws客户端、服务端进行数据交换时,协议控制的数据包头部较小。在不包含头部的状况下,服务端到客户端的包头只有2~10字节(取决于数据包长度),客户端到服务端的的话,须要加上额外的4字节的掩码。而HTTP协议每次通讯都须要携带完整的头部。
  4. 支持扩展。ws协议定义了扩展,用户能够扩展协议,或者实现自定义的子协议。(好比支持自定义压缩算法等)
WebSocket如何创建链接

WebSocket复用了HTTP的握手通道。具体指的是,客户端经过HTTP请求与WebSocket服务端协商升级协议。协议升级完成后,后续的数据交换则遵守WebSocket的协议。

客户端:申请协议升级

首先,客户端发起协议升级请求。能够看到,采用的是标准的HTTP报文格式,且只支持GET方法。

GET  / HTTP/1.1  
Host: localhost:8080  
Origin: http://127.0.0.1:3000  
Connection: Upgrade  
Upgrade: websocket  
Sec-WebSocket-Version: 13  
Sec-WebSocket-Key: w4v7O6xFTi36lq3RNcgctw==```
  • Connection: Upgrade:表示要升级协议
  • Upgrade: websocket:表示要升级到websocket协议。
  • Sec-WebSocket-Version: 13:表示websocket的版本。若是服务端不支持该版本,须要返回一个Sec-WebSocket-Version header,里面包含服务端支持的版本号。
  • Sec-WebSocket-Key:与后面服务端响应首部的Sec-WebSocket-Accept是配套的,提供基本的防御,好比恶意的链接,或者无心的链接。
注意,上面请求省略了部分非重点请求首部。因为是标准的HTTP请求,相似Host、Origin、Cookie等请求首部会照常发送。在握手阶段,能够经过相关请求首部进行 安全限制、权限校验等。
服务端:响应协议升级

服务端返回内容以下,状态代码101表示协议切换。到此完成协议升级,后续的数据交互都按照新的协议来。

HTTP/1.1 101 Switching Protocols  
Connection: Upgrade 
Upgrade: websocket  
Sec-WebSocket-Accept: Oy4NRAQ13jhfONC7bP8dTKb4PTU=

备注:每一个header都以\r\n结尾,而且最后一行加上一个额外的空行\r\n。此外,服务端回应的HTTP状态码只能在握手阶段使用。过了握手阶段后,就只能采用特定的错误码。

Sec-WebSocket-Accept的计算

Sec-WebSocket-Accept根据客户端请求首部的Sec-WebSocket-Key计算出来。

计算公式为:

  1. Sec-WebSocket-Key258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼接。
  2. 经过SHA1计算出摘要,并转成base64字符串。

伪代码以下:

toBase64( sha1( Sec-WebSocket-Key + 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 ))
数据帧格式

客户端、服务端数据的交换,离不开数据帧格式的定义。所以,在实际讲解数据交换以前,咱们先来看下WebSocket的数据帧格式。

WebSocket客户端、服务端通讯的最小单位是帧(frame),由1个或多个帧组成一条完整的消息(message

  1. 发送端:将消息切割成多个帧,并发送给服务端;
  2. 接收端:接收消息帧,并将关联的帧从新组装成完整的消息;

WechatIMG13606.jpeg

Mask: 1个比特。
表示是否要对数据载荷进行掩码操做。从客户端向服务端发送数据时,须要对数据进行掩码操做;从服务端向客户端发送数据时,不须要对数据进行掩码操做。若是服务端接收到的数据没有进行过掩码操做,服务端须要断开链接。
若是Mask是1,那么在Masking-key中会定义一个掩码键(masking key),并用这个掩码键来对数据载荷进行反掩码。全部客户端发送到服务端的数据帧,Mask都是1。
数据传递
FIN:1个比特。
若是是1,表示这是消息(message)的最后一个分片(fragment),若是是0,表示不是是消息(message)的最后一个分片(fragment)。
RSV1, RSV2, RSV3:各占1个比特。
通常状况下全为0。当客户端、服务端协商采用WebSocket扩展时,这三个标志位能够非0,且值的含义由扩展进行定义。若是出现非零的值,且并无采用WebSocket扩展,链接出错。
Opcode: 4个比特。
操做代码,Opcode的值决定了应该如何解析后续的数据载荷(data payload)。若是操做代码是不认识的,那么接收端应该断开链接(fail the connection)。

数据传递
一旦WebSocket客户端、服务端创建链接后,后续的操做都是基于数据帧的传递。
WebSocket根据 opcode来区分操做的类型。好比 0x8表示断开链接, 0x0- 0x2表示数据交互。

一、数据分片

WebSocket的每条消息可能被切分红多个数据帧。当WebSocket的接收方收到一个数据帧时,会根据 FIN的值来判断,是否已经收到消息的最后一个数据帧。

FIN=1表示当前数据帧为消息的最后一个数据帧,此时接收方已经收到完整的消息,能够对消息进行处理。FIN=0,则接收方还须要继续监听接收其他的数据帧。

此外,opcode在数据交换的场景下,表示的是数据的类型。0x01表示文本,0x02表示二进制。而0x00比较特殊,表示延续帧(continuation frame),顾名思义,就是完整消息对应的数据帧还没接收完。

二、数据分片例子

FIN=1, 表示是当前消息的最后一个数据帧。服务端收到当前数据帧后,能够处理消息。opcode=0x1,表示客户端发送的是文本类型。
举例

  1. FIN=0,opcode=0x1,表示发送的是文本类型,且消息还没发送完成,还有后续的数据帧。
  2. FIN=0,opcode=0x0,表示消息还没发送完成,还有后续的数据帧,当前的数据帧须要接在上一条数据帧以后。
  3. FIN=1,opcode=0x0,表示消息已经发送完成,没有后续的数据帧,当前的数据帧须要接在上一条数据帧以后。服务端能够将关联的数据帧组装成完整的消息。
链接保持+心跳

WebSocket为了保持客户端、服务端的实时双向通讯,须要确保客户端、服务端之间的TCP通道保持链接没有断开。然而,对于长时间没有数据往来的链接,若是依旧长时间保持着,可能会浪费包括的链接资源。
但不排除有些场景,客户端、服务端虽然长时间没有数据往来,但仍须要保持链接。这个时候,能够采用心跳来实现。

  • 发送方->接收方:ping
  • 接收方->发送方:pong

ping、pong的操做,对应的是WebSocket的两个控制帧,opcode分别是0x90xA

举例,WebSocket服务端向客户端发送ping,只须要以下代码(采用ws模块)

ws.ping('', false, true);
Sec-WebSocket-Key/Accept的做用

前面提到了,Sec-WebSocket-Key/Sec-WebSocket-Accept在主要做用在于提供基础的防御,减小恶意链接、意外链接。

做用大体概括以下:

  1. 避免服务端收到非法的websocket链接(好比http客户端不当心请求链接websocket服务,此时服务端能够直接拒绝链接)
  2. 确保服务端理解websocket链接。由于ws握手阶段采用的是http协议,所以可能ws链接是被一个http服务器处理并返回的,此时客户端能够经过Sec-WebSocket-Key来确保服务端认识ws协议。(并不是百分百保险,好比老是存在那么些无聊的http服务器,光处理Sec-WebSocket-Key,但并无实现ws协议。。。)
  3. 用浏览器里发起ajax请求,设置header时,Sec-WebSocket-Key以及其余相关的header是被禁止的。这样能够避免客户端发送ajax请求时,意外请求协议升级(websocket upgrade
  4. 能够防止反向代理(不理解ws协议)返回错误的数据。好比反向代理先后收到两次ws链接的升级请求,反向代理把第一次请求的返回给cache住,而后第二次请求到来时直接把cache住的请求给返回(无心义的返回)。
  5. Sec-WebSocket-Key主要目的并非确保数据的安全性,由于Sec-WebSocket-KeySec-WebSocket-Accept的转换计算公式是公开的,并且很是简单,最主要的做用是预防一些常见的意外状况(非故意的)。
强调:Sec-WebSocket-Key/Sec-WebSocket-Accept 的换算,只能带来基本的保障,但链接是否安全、数据是否安全、客户端/服务端是否合法的 ws客户端、ws服务端,其实并无实际性的保证。

JS

介绍 js 的基本数据类型。

js 一共有六种基本数据类型,分别是 Undefined、Null、Boolean、Number、String,还有在 ES6 中新增的 Symbol 类型,表明建立后独一无二且不可变的数据类型,它的出现我认为主要是为了解决可能出现的全局变量冲突的问题。

JavaScript 有几种类型的值?你能画一下他们的内存图吗?

js 能够分为两种类型的值,一种是基本数据类型,一种是复杂数据类型。
基本数据类型(Undefined、Null、Boolean、Number、String)
复杂数据类型指的是 Object 类型,全部其余的如 Array、Date 等数据类型均可以理解为 Object 类型的子类。

栈类型:
屏幕快照 2020-05-17 下午12.50.09.png
堆类型:
屏幕快照 2020-05-17 下午12.50.23.png

两种类型间的主要区别是它们的存储位置不一样
基本数据类型的值直接保存在栈中
复杂数据类型的值保存在堆中,经过使用在栈中保存对应的指针来获取堆中的值。

什么是堆?什么是栈?它们之间有什么区别和联系?

堆和栈的概念存在于数据结构中和操做系统内存中。

在数据结构中
栈中数据的存取方式为先进后出。而堆是一个优先队列,是按优先级来进行排序的,优先级能够按照大小来规定。彻底二叉树是堆的一种实现方式。

在操做系统中,内存被分为栈区和堆区。
栈区内存由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操做方式相似于数据结构中的栈。
堆区内存通常由程序员分配释放,若程序员不释放,程序结束时可能由垃圾回收机制回收。

内部属性 [[Class]] 是什么?

全部 typeof 返回值为 "object" 的对象(如数组)都包含一个内部属性 [[Class]](咱们能够把它看做一个内部的分类,而非传统的面向对象意义上的类)。这个属性没法直接访问,通常经过 Object.prototype.toString(..) 来查看。例如:
Object.prototype.toString.call( [1,2,3] );
// "[object Array]"
Object.prototype.toString.call( /regex-literal/i );
// "[object RegExp]"

介绍 js 有哪些内置对象?

js 中的内置对象主要指的是在程序执行前存在全局做用域里的由 js 定义的一些全局值属性、函数和用来实例化其余对象的构造函数对象。通常咱们常常用到的如:
全局变量值 NaN、undefined,
全局函数如 parseInt()、parseFloat()
基本对象如 Object、Function、Boolean、Symbol
用来实例化对象的构造函数如 Date、Object
表示和操做字符串的对象如 String、RegExp
还有提供数学计算的单体内置对象如 Math 对象。

undefined 与 undeclared 的区别?

已在做用域中声明但尚未赋值的变量,是 undefined 的。相反,尚未在做用域中声明过的变量,是 undeclared 的。

对于 undeclared 变量的引用,浏览器会报引用错误,如ReferenceError: b is not defined 。可是咱们可使用 typeof 的安全防范机制来避免报错,由于对于 undeclared(或者 not defined )变量,typeof 会返回 "undefined"。

null 和 undefined 的区别?

CSS

介绍一下标准的 CSS 的盒子模型?低版本 IE 的盒子模型有什么不一样的?

盒模型都是由四个部分组成的,分别是margin、border、padding和content。
标准盒模型和IE盒模型的区别在于设置width和height时,所对应的范围不一样。标准盒模型的width和height属性的范围只包含了content,而IE盒模型的width和height属性的范围包含了border、padding和content。

css的盒模型由content(内容)、padding(内边距)、border(边框)、margin(外边距)组成。但盒子的大小由content+padding+border这几部分决定,把margin算进去的那是盒子占据的位置,而不是盒子的大小

通常来讲,咱们能够经过修改元素的box-sizing属性来改变元素的盒模型。

CSS 选择符有哪些

(1)id选择器(#myid)
(2)类选择器(.myclassname)
(3)标签选择器(div,h1,p)
(4)后代选择器(h1p)
(5)相邻后代选择器(子)选择器(ul>li)
(6)兄弟选择器(li~a)
(7)相邻兄弟选择器(li+a)
(8)属性选择器(a[rel="external"])
(9)伪类选择器(a:hover,li:nth-child)
(10)伪元素选择器(::before、::after)
(11)通配符选择器(*)

::before 和:after 中双冒号和单冒号有什么区别?解释一下这 2 个伪元素的做用

在css3中使用单冒号来表示伪类,用双冒号来表示伪元素。可是为了兼容已有的伪元素的写法,在一些浏览器中也可使用单冒号来表示伪元素。

伪类通常匹配的是元素的一些特殊状态,如hover、link等,而伪元素通常匹配的特殊的位置,好比after、before等。

伪类与伪元素的区别

css引入伪类和伪元素概念是为了格式化文档树之外的信息。也就是说,伪类和伪元素是用来修饰不在文档树中的部分,好比,一句话中的第一个字母,或者是列表中的第一个元素。

伪类用于当已有的元素处于某个状态时,为其添加对应的样式,这个状态是根据用户行为而动态变化的。好比说,当用户悬停在指定的元素时,咱们能够经过 :hover来描述这个元素的状态。

伪元素用于建立一些不在文档树中的元素,并为其添加样式。它们容许咱们为元素的某些部分设置样式。好比说,咱们能够经过::before来在一个元素前增长一些文本,并为这些文本添加样式。虽然用户能够看到这些文本,可是这些文本实际上不在文档树中。

有时你会发现伪元素使用了两个冒号(::)而不是一个冒号(:)。这是CSS3的一部分,并尝试区分伪类和伪元素。大多数浏览器都支持这两个值。按照规则应该使用(::)而不是(:),从而区分伪类和伪元素。可是,因为在旧版本的W3C规范并未对此进行特别区分,所以目前绝大多数的浏览器都支持使用这两种方式表示伪元素。

相关文章
相关标签/搜索