面试模板

121 阅读42分钟

计算机基础 - 网络

简述 OSI 网路模型(7层/4层网络协议)

简单:简述 TCP 三次握手过程

进阶:为什么建立连接需要 3 次握手,断开却需要 4 次握手

解答:TCP 三次握手的过程

第一次握手,客户端向服务器发送一个 SYN 连接请求报文段,报文段的首部中 SYN 标志位置为1,序号字段是一个任选的 随机数。它代表的是客户端数据的初始序号。

第二次握手,服务器端接收到客户端发送的 SYN 连接请求报文段后,服务器首先会为该连接分配 TCP 缓存和变量,然后向 客户端发送 SYN ACK 报文段,报文段的首部中 SYN 和 ACK 标志位都被置为1,代表这是一个对 SYN 连接请求的确认, 同时序号字段是服务器端产生的一个任选的随机数,它代表的是服务器端数据的初始序号。确认号字段为客户端发送的序号加 一。

第三次握手,客户端接收到服务器的肯定应答后,它也会为这次 TCP 连接分配缓存和变量,同时向服务器端发送一个对服务 器端的报文段的确认。第三次握手可以在报文段中携带数据。

链接

三次握手过程理解

第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

四次挥手

1)客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。

2)服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。

3)客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。

4)服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。

5)客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。

6)服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

blog.csdn.net/qq_38950316…

简述常用的 HTTP 状态码

简述http: HTTP 是超文本传输协议,它定义了客户端和服务器之间交换报文的格式和方式,默认使用 80 端口。它使用 TCP 作为传 输层协议,保证了数据传输的可靠性。

HTTP 是一个无状态的协议,HTTP 服务器不会保存关于客户的任何信息。

100、200、300(301/302、304、307/308)、400(401、403、404)、500

Get 和 POST 请求的区别

解答:Post 和 Get 是 HTTP 请求的两种方法。 (1)从应用场景上来说,GET 请求是一个幂等的请求,一般 Get 请求用于对服务器资源不会产生影响的场景,比如说请求一个网 页。而 Post 不是一个幂等的请求,一般用于对服务器资源会产生影响的情景。比如注册用户这一类的操作。 (2)因为不同的应用场景,所以浏览器一般会对 Get 请求缓存,但很少对 Post 请求缓存。 (3)从发送的报文格式来说,Get 请求的报文中实体部分为空,Post 请求的报文中实体部分一般为向服务器发送的数据。 (4)但是 Get 请求也可以将请求的参数放入 url 中向服务器发送,这样的做法相对于 Post 请求来说,一个方面是不太安全, 因为请求的 url 会被保留在历史记录中。并且浏览器由于对 url 有一个长度上的限制,所以会影响 get 请求发送数据时 的长度。这个限制是浏览器规定的,并不是 RFC 规定的。还有就是 post 的参数传递支持更多的数据类型。

(1)post更安全(不会作为url的一部分,不会被缓存、保存在服务器日志、以及浏览器浏览记录中) (2)post发送的数据更大,get请求 url 长度有限制(get因为浏览器和Web服务器限制,url 有长度限制) (3)post能发送更多的数据类型(get只能发送ASCII字符) (4)post比get慢(一次请求,post 需发送 2 个 TCP 数据包 ) (5)post用于修改和写入数据,get一般用于搜索排序和筛选之类的操作

TCP 和 UDP 的区别

TCP与UDP区别总结:

1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接

2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付 3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的 UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等) 4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信 5、TCP首部开销20字节;UDP的首部开销小,只有8个字节

6、TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

www.cnblogs.com/fundebug/p/…

HTTP Header 信息

www.cnblogs.com/jycboy/p/ht…

计算机基础

面向对象的三个特性,五个原则

三个特性:封装、继承、多态

1、封装:隐藏对象属性和实现细节,仅对外提供公共访问方式,隔离变化,便于使用,提高复用性和安全性。 2、继承:提高代码复用性;继承是多态的前提。 3、多态:父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。提高了程序的拓展性。

五个原则:单一职责(SRP)、开放封闭(OCP)、里式替换(LSP)、依赖倒置(DIP)、接口隔离(ISP)

1、单一职责原则 SRP(Single Responsibility Principle):类的功能要单一。 2、开放封闭原则 OCP(Open-Close Principle):一个模块对于拓展开放,对修改封闭。 3、里式替换原则 LSP(the Liskov Substitution Principle LSP):子类可以替换父类出现在父类能够出现的任何地方。对父类的调用同样适用于子类 4、依赖倒置原则 DIP(the Dependency Inversion Principle DIP):高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。 5、接口隔离原则 ISP(the Interface Segregation Principle ISP):设计时采用多个与特定客户类有关的接口比采用一个通用的接口要好。

Html

*DOCTYPE 的作用是什么?

知识点:IE5.5 引入了文档模式的概念,而这个概念是通过使用文档类型(DOCTYPE)切换实现的。 <!DOCTYPE>声明位于 HTML 文档中的第一行,处于 标签之前。告知浏览器的解析器用什么文档标准解析这个文档。 DOCTYPE 不存在或格式不正确会导致文档以兼容模式呈现。

解答:<!DOCTYPE> 声明一般位于文档的第一行,它的作用主要是告诉浏览器以什么样的模式来解析文档。一般指定了之后会以标准模式来 进行文档解析,否则就以兼容模式进行解析。在标准模式下,浏览器的解析规则都是按照最新的标准进行解析的。而在兼容模式下,浏 览器会以向后兼容的方式来模拟老式浏览器的行为,以保证一些老的网站的正确访问。 在 html5 之后不再需要指定 DTD 文档,因为 html5 以前的 html 文档都是基于 SGML 的,所以需要通过指定 DTD 来定义文 档中允许的属性以及一些规则。而 html5 不再基于 SGML 了,所以不再需要使用 DTD。

HTML5 为什么只需要写 ,而不需要引入 DTD?

解答:HTML5 不基于 SGML,因此不需要对 DTD 进行引用,但是需要 DOCTYPE 来规范浏览器的行为(让浏览器按照它们应该的方式来运 行)。 而 HTML4.01 基于 SGML ,所以需要对 DTD 进行引用,才能告知浏览器文档所使用的文档类型。

*行内元素与块级元素的区别?

解答:HTML4中,元素被分成两大类:inline (内联元素)与 block (块级元素)。 (1) 格式上,默认情况下,行内元素不会以新行开始,而块级元素会新起一行。 (2) 内容上,默认情况下,行内元素只能包含文本和其他行内元素。而块级元素可以包含行内元素和其他块级元素。 (3) 行内元素与块级元素属性的不同,主要是盒模型属性上:行内元素设置 width 无效,height 无效(可以设置 line-hei ght),设置 margin 和 padding 的上下不会对其他元素产生影响。

常见的行内元素有 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

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

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

*CSS 如何阻塞文档解析?

解答:理论上,既然样式表不改变 DOM 树,也就没有必要停下文档的解析等待它们,然而,存在一个问题,JavaScript 脚本执行时可 能在文档的解析过程中请求样式信息,如果样式还没有加载和解析,脚本将得到错误的值,显然这将会导致很多问题。 所以如果浏览器尚未完成 CSSOM 的下载和构建,而我们却想在此时运行脚本,那么浏览器将延迟 JavaScript 脚本执行和文档 的解析,直至其完成 CSSOM 的下载和构建。也就是说,在这种情况下,浏览器会先下载和构建 CSSOM,然后再执行 JavaScript, 最后再继续文档的解析。

*什么是重绘和回流?

解答:重绘: 当渲染树中的一些元素需要更新属性,而这些属性只是影响元素的外观、风格,而不会影响布局的操作,比如 background -color,我们将这样的操作称为重绘。 回流:当渲染树中的一部分(或全部)因为元素的规模尺寸、布局、隐藏等改变而需要重新构建的操作,会影响到布局的操作,这样 的操作我们称为回流。

常见引起回流属性和方法: 任何会改变元素几何信息(元素的位置和尺寸大小)的操作,都会触发回流。 (1)添加或者删除可见的 DOM 元素; (2)元素尺寸改变——边距、填充、边框、宽度和高度 (3)内容变化,比如用户在 input 框中输入文字 (4)浏览器窗口尺寸改变——resize事件发生时 (5)计算 offsetWidth 和 offsetHeight 属性 (6)设置 style 属性的值 (7)当你修改网页的默认字体时。

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

*DOMContentLoaded 事件和 Load 事件的区别?

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

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

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

请描述一下 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 在所有同源窗口中都是共享的。

CSS

*介绍一下标准的 CSS 的盒子模型?

解答:盒模型都是由四个部分组成的,分别是 margin、border、padding 和 content。 标准盒模型和 IE 盒模型的区别在于设置 width 和 height 时,所对应的范围不同。标准盒模型的 width 和 height 属性的 范围只包含了 content,而 IE 盒模型的 width 和 height 属性的范围包含了 border、padding 和 content。 一般来说,我们可以通过修改元素的 box-sizing 属性来改变元素的盒模型。

*CSS选择器有哪些类型?

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

*如何居中 div ?

居中

display 有哪些值?说明他们的作用。

block 块类型。默认宽度为父元素宽度,可设置宽高,换行显示。 none 元素不显示,并从文档流中移除。 inline 行内元素类型。默认宽度为内容宽度,不可设置宽高,同行显示。 inline-block 默认宽度为内容宽度,可以设置宽高,同行显示。 list-item 像块类型元素一样显示,并添加样式列表标记。 table 此元素会作为块级表格来显示。 inherit 规定应该从父元素继承 display 属性的值。

position 的值 relative 和 absolute 定位原点是?

知识点:absolute 生成绝对定位的元素,相对于值不为 static 的第一个父元素的 padding box 进行定位,也可以理解为离自己这一级元素最近的 一级 position 设置为 absolute 或者 relative 的父元素的 padding box 的左上角为原点的。 fixed (老IE不支持) 生成绝对定位的元素,相对于浏览器窗口进行定位。 relative 生成相对定位的元素,相对于其元素本身所在正常位置进行定位。 static 默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right, z-index 声明)。 inherit 规定从父元素继承 position 属性的值。

解答:relative 定位的元素,是相对于元素本身的正常位置来进行定位的。 absolute 定位的元素,是相对于它的第一个 position 值不为 static 的祖先元素的 padding box 来进行定位的。这句话 我们可以这样来理解,我们首先需要找到绝对定位元素的一个 position 的值不为 static 的祖先元素,然后相对于这个祖先元 素的 padding box 来定位,也就是说在计算定位距离的时候,padding 的值也要算进去。

*style 标签写在 body 后与 body 前有什么区别?

解答:页面加载自上而下 当然是先加载样式。写在 body 标签后由于浏览器以逐行方式对 HTML 文档进行解析,当解析到写在尾部的样式 表(外联或写在 style 标签)会导致浏览器停止之前的渲染,等待加载且解析样式表完成之后重新渲染,在 windows 的 IE 下可 能会出现 FOUC 现象(即样式失效导致的页面闪烁问题)

简述Flex

解答:flex 布局是 CSS3 新增的一种布局方式,我们可以通过将一个元素的 display 属性值设置为 flex 从而使它成为一个 flex 容器,它的所有子元素都会成为它的项目。 一个容器默认有两条轴,一个是水平的主轴,一个是与主轴垂直的交叉轴。我们可以使用 flex-direction 来指定主轴的方向。 我们可以使用 justify-content 来指定元素在主轴上的排列方式,使用 align-items 来指定元素在交叉轴上的排列方式。还 可以使用 flex-wrap 来规定当一行排列不下时的换行方式。 对于容器中的项目,我们可以使用 order 属性来指定项目的排列顺序,还可以使用 flex-grow 来指定当排列空间有剩余的时候, 项目的放大比例。还可以使用 flex-shrink 来指定当排列空间不足时,项目的缩小比例。

margin 重叠问题的理解。

解答:margin 重叠指的是在垂直方向上,两个相邻元素的 margin 发生重叠的情况。 一般来说可以分为四种情形: 第一种是相邻兄弟元素的 marin-bottom 和 margin-top 的值发生重叠。这种情况下我们可以通过设置其中一个元素为 BFC 来解决。 第二种是父元素的 margin-top 和子元素的 margin-top 发生重叠。它们发生重叠是因为它们是相邻的,所以我们可以通过这 一点来解决这个问题。我们可以为父元素设置 border-top、padding-top 值来分隔它们,当然我们也可以将父元素设置为 BFC 来解决。 第三种是高度为 auto 的父元素的 margin-bottom 和子元素的 margin-bottom 发生重叠。它们发生重叠一个是因为它们相 邻,一个是因为父元素的高度不固定。因此我们可以为父元素设置 border-bottom、padding-bottom 来分隔它们,也可以为 父元素设置一个高度,max-height 和 min-height 也能解决这个问题。当然将父元素设置为 BFC 是最简单的方法。 第四种情况,是没有内容的元素,自身的 margin-top 和 margin-bottom 发生的重叠。我们可以通过为其设置 border、pa dding 或者高度来解决这个问题。

对 BFC 规范(块级格式化上下文:block formatting context)的理解?

知识点:块格式化上下文(Block Formatting Context,BFC)是 Web 页面的可视化 CSS 渲染的一部分,是布局过程中生成块级盒 子的区域,也是浮动元素与其他元素的交互限定区域。 通俗来讲 • BFC 是一个独立的布局环境,可以理解为一个容器,在这个容器中按照一定规则进行物品摆放,并且不会影响其它环境中的物品。 • 如果一个元素符合触发 BFC 的条件,则 BFC 中的元素布局不受外部影响。

创建 BFC (1)根元素或包含根元素的元素 (2)浮动元素 float = left | right 或 inherit(≠ none) (3)绝对定位元素 position = absolute 或 fixed (4)display = inline-block | flex | inline-flex | table-cell 或 table-caption (5)overflow = hidden | auto 或 scroll (≠ visible)

解答:BFC 指的是块级格式化上下文,一个元素形成了 BFC 之后,那么它内部元素产生的布局不会影响到外部元素,外部元素的布局也 不会影响到 BFC 中的内部元素。一个 BFC 就像是一个隔离区域,和其他区域互不影响。 一般来说根元素是一个 BFC 区域,浮动和绝对定位的元素也会形成 BFC,display 属性的值为 inline-block 、flex 这些 属性时也会创建 BFC。还有就是元素的 overflow 的值不为 visible 时都会创建 BFC。

设备像素、css 像素、设备独立像素、dpr、ppi 之间的区别?

解答:设备像素指的是物理像素,一般手机的分辨率指的就是设备像素,一个设备的设备像素是不可变的。 css 像素和设备独立像素是等价的,不管在何种分辨率的设备上,css 像素的大小应该是一致的,css 像素是一个相对单位,它是相 对于设备像素的,一个 css 像素的大小取决于页面缩放程度和 dpr 的大小。 dpr 指的是设备像素和设备独立像素的比值,一般的 pc 屏幕,dpr = 1。在 iphone4 时,苹果推出了 retina 屏幕,它的 dpr 为2。屏幕的缩放会改变 dpr 的值。 ppi 指的是每英寸的物理像素的密度,ppi 越大,屏幕的分辨率越大。

几种常见的 CSS 布局

juejin.cn/post/684490…

如何实现单行/多行文本溢出的省略(...)?

解答:

单行文本溢出 p { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

多行文本溢出 p { position: relative; line-height: 1.5em; /* 高度为需要显示的行数*行高,比如这里我们显示两行,则为3 */ height: 3em; overflow: hidden; } p:after { content: "..."; position: absolute; bottom: 0; right: 0; background-color: #fff; }

css 两栏布局的实现?

github.com/CavsZhouyou… 100 题

Js

*介绍 js 的基本数据类型

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

*JavaScript 有几种类型的值,存储方式是怎样的?

栈:原始数据类型(Undefined、Null、Boolean、Number、String) 堆:引用数据类型(对象、数组和函数)

*堆和栈有什么区别和联系?

堆和栈的概念存在于数据结构中和操作系统内存中。 在数据结构中,栈中数据的存取方式为先进后出。而堆是一个优先队列,是按优先级来进行排序的,优先级可以按照大小来规定。完全 二叉树是堆的一种实现方式。 在操作系统中,内存被分为栈区和堆区。 栈区内存由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 堆区内存一般由程序员分配释放,若程序员不释放,程序结束时可能由垃圾回收机制回收。

*介绍 js 有哪些内置对象?

js 中的内置对象主要指的是在程序执行前存在全局作用域里的由 js 定义的一些全局值属性、函数和用来实例化其他对象的构造函 数对象。一般我们经常用到的如全局变量值 NaN、undefined,全局函数如 parseInt()、parseFloat() 用来实例化对象的构 造函数如 Date、Object 等,还有提供数学计算的单体内置对象如 Math 对象。

什么是变量提升?

JavaScript 中,函数及变量的声明都将被提升到函数的最顶部。

JavaScript 中,变量可以在使用后声明,也就是变量可以先使用再声明。

*let 和 const 的注意点?

(1)声明的变量只在声明时的代码块内有效 (2)不存在声明提升 (3)存在暂时性死区,如果在变量声明前使用,会报错 (4)不允许重复声明,重复声明会报错

*null 和 undefined 的区别?

首先 Undefined 和 Null 都是基本数据类型,这两个基本数据类型分别都只有一个值,就是 undefined 和 null。 undefined 代表的含义是未定义,null 代表的含义是空对象。一般变量声明了但还没有定义的时候会返回 undefined,null 主要用于赋值给一些可能会返回对象的变量,作为初始化。 undefined 在 js 中不是一个保留字,这意味着我们可以使用 undefined 来作为一个变量名,这样的做法是非常危险的,它 会影响我们对 undefined 值的判断。但是我们可以通过一些方法获得安全的 undefined 值,比如说 void 0。 当我们对两种类型使用 typeof 进行判断的时候,Null 类型化会返回 “object”,这是一个历史遗留的问题。当我们使用双等 号对两种类型的值进行比较时会返回 true,使用三个等号时会返回 false。

*== 和 === 有什么区别?

=== 不需要进行类型转换,只有类型相同并且值相等时,才返回 true.

*for of , for in 和 forEach,map 的区别

for...of 循环:具有 iterator 接口,就可以用 for...of 循环遍历它的成员 (属性值)。for...of 循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象、Generator 对象,以及字符串。for...of 循环调用遍历器接口,数组的遍历器接口只返回具有数字索引的属性。对于普通的对象,for...of 结构不能直接使用,会报错,必须部署了 Iterator 接口后才能使用。可以中断循环。

for...in 循环:遍历对象自身的和继承的可枚举的属性, 不能直接获取属性值。可以中断循环。

forEach: 只能遍历数组,不能中断,没有返回值 (或认为返回值是 undefined)。

map: 只能遍历数组,不能中断,返回值是修改后的数组。

*如何判断一个变量是不是数组?(回答其一即可)

使用 Array.isArray 判断,如果返回 true, 说明是数组;

使用 instanceof Array 判断,如果返回 true, 说明是数组;

使用 Object.prototype.toString.call 判断,如果值是 [object Array], 说明是数组;

通过 constructor 来判断,如果是数组,那么 arr.constructor === Array. (不准确,因为我们可以指定 obj.constructor = Array)。

*JavaScript 原型,原型链? 有什么特点?

解答:在 js 中我们是使用构造函数来新建一个对象的,每一个构造函数的内部都有一个 prototype 属性值,这个属性值是一个对 象,这个对象包含了可以由该构造函数的所有实例共享的属性和方法。当我们使用构造函数新建一个对象后,在这个对象的内部 将包含一个指针,这个指针指向构造函数的 prototype 属性对应的值,在 ES5 中这个指针被称为对象的原型。一般来说我们 是不应该能够获取到这个值的,但是现在浏览器中都实现了 proto 属性来让我们访问这个属性,但是我们最好不要使用这 个属性,因为它不是规范中规定的。ES5 中新增了一个 Object.getPrototypeOf() 方法,我们可以通过这个方法来获取对 象的原型。 当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又 会有自己的原型,于是就这样一直找下去,也就是原型链的概念。原型链的尽头一般来说都是 Object.prototype 所以这就 是我们新建的对象为什么能够使用 toString() 等方法的原因。

特点: JavaScript 对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与 之相关的对象也会继承这一改变。

*js 获取原型的方法?

解答:(1)p.proto (2)p.constructor.prototype (3)Object.getPrototypeOf(p)

*typeof NaN 的结果是什么?

解答:NaN 意指“不是一个数字”(not a number),NaN 是一个“警戒值”(sentinel value,有特殊用途的常规值),用于指出 数字类型中的错误情况,即“执行数学运算没有成功,这是失败后返回的结果”。 typeof NaN; // "number" NaN 是一个特殊值,它和自身不相等,是唯一一个非自反(自反,reflexive,即 x === x 不成立)的值。而 NaN != NaN 为 true。

typeof 是否正确判断类型? instanceof 呢?

首先 typeof 能够正确的判断基本数据类型,但是除了 null, typeof null 输出的是对象。

但是对象来说,typeof 不能正确的判断其类型, typeof 一个函数可以输出 'function', 而除此之外,输出的全是 object, 这种情况下,我们无法准确的知道对象的类型。

instanceof 可以准确的判断复杂数据类型,但是不能正确判断基本数据类型。

什么是闭包,为什么要用它?

解答:闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,创建的函数可以 访问到当前函数的局部变量。

闭包有两个常用的用途。 闭包的第一个用途是使我们在函数外部能够访问到函数内部的变量。通过使用闭包,我们可以通过在外部调用闭包函数,从而在外 部访问到函数内部的变量,可以使用这种方法来创建私有变量。 函数的另一个用途是使已经运行结束的函数上下文中的变量对象继续留在内存中,因为闭包函数保留了这个变量对象的引用,所以 这个变量对象不会被回收。

其实闭包的本质就是作用域链的一个特殊的应用,只要了解了作用域链的创建过程,就能够理解闭包的实现原理。

闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包最常用的方式就是在一个函数内部创建另一个函数。

闭包的作用有:

封装私有变量;

模仿块级作用域 (ES5 中没有块级作用域);

实现 JS 的模块。

*事件委托是什么?

解答:事件委托本质上是利用了浏览器事件冒泡的机制。因为事件在冒泡过程中会上传到父节点,并且父节点可以通过事件对象获取到 目标节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件,这种方式称为事件 代理。 使用事件代理我们可以不必要为每一个子元素都绑定一个监听事件,这样减少了内存上的消耗。并且使用事件代理我们还可以实 现事件的动态绑定,比如说新增了一个子节点,我们并不需要单独地为它添加一个监听事件,它所发生的事件会交给父元素中的 监听函数来处理。

DOM 操作——怎样添加、移除、移动、复制、创建和查找节点?

解答:(1)创建新节点 createDocumentFragment(node) createElement(node) createTextNode(text) (2)添加、移除、替换、插入 appendChild(node) removeChild(node) replaceChild(new,old) insertBefore(new,old) (3)查找 getElementById() getElementsByName() getElementsByTagName() getElementsByClassName() querySelector() querySelectorAll() (4)属性操作 getAttribute(key) setAttribute(key,value) hasAttribute(key) removeAttribute(key)

*谈谈 This 对象的理解。

解答:this 是执行上下文中的一个属性,它指向最后一次调用这个方法的对象。在实际开发中,this 的指向可以通过四种调用模 式来判断。(1)第一种是函数调用模式,当一个函数不是一个对象的属性时,直接作为函数来调用时,this 指向全局对象。 (2)第二种是方法调用模式,如果一个函数作为一个对象的方法来调用时,this 指向这个对象。 (3)第三种是构造器调用模式,如果一个函数用 new 调用时,函数执行前会新创建一个对象,this 指向这个新创建的对 象。 (4)第四种是 apply 、 call 和 bind 调用模式,这三个方法都可以显示的指定调用函数的 this 指向。其中 apply 方法接收两个参数:一个是 this 绑定的对象,一个是参数数组。call 方法接收的参数,第一个是 this 绑定的对象 ,后面的其余参数是传入函数执行的参数。也就是说,在使用 call() 方法时,传递给函数的参数必须逐个列举出来。b ind 方法通过传入一个对象,返回一个 this 绑定了传入对象的新函数。这个函数的 this 指向除了使用 new 时会 被改变,其他情况下都不会改变。

*.call() 和 .apply() 的区别?

解答:它们的作用一模一样,区别仅在于传入参数的形式的不同。 apply 接受两个参数,第一个参数指定了函数体内 this 对象的指向,第二个参数为一个带下标的集合,这个集合可以为数组, 也可以为类数组,apply 方法把这个集合中的元素作为参数传递给被调用的函数。 call 传入的参数数量不固定,跟 apply 相同的是,第一个参数也是代表函数体内的 this 指向,从第二个参数开始往后,每 个参数被依次传入函数。

对于 JSON 的了解?

知识点:JSON 是一种数据交换格式,基于文本,优于轻量,用于交换数据。 JSON 可以表示数字、布尔值、字符串、null、数组(值的有序序列),以及由这些值(或数组、对象)所组成的对象(字符串与 值的映射)。 JSON 使用 JavaScript 语法,但是 JSON 格式仅仅是一个文本。文本可以被任何编程语言读取及作为数据格式传递。

*Ajax 是什么? 如何创建一个Ajax?

解答:我对 ajax 的理解是,它是一种异步通信的方法,通过直接由 js 脚本向服务器发起 http 通信,然后根据服务器返回的数据, 更新网页的相应部分,而不用刷新整个页面的一种方法。 创建一个 ajax 有这样几个步骤 首先是创建一个 XMLHttpRequest 对象。 然后在这个对象上使用 open 方法创建一个 http 请求,open 方法所需要的参数是请求的方法、请求的地址、是否异步和用户 的认证信息。 在发起请求前,我们可以为这个对象添加一些信息和监听函数。比如说我们可以通过 setRequestHeader 方法来为请求添加头信 息。我们还可以为这个对象添加一个状态监听函数。一个 XMLHttpRequest 对象一共有 5 个状态,当它的状态变化时会触发on readystatechange 事件,我们可以通过设置监听函数,来处理请求成功后的结果。当对象的 readyState 变为 4 的时候,代 表服务器返回的数据接收完成,这个时候我们可以通过判断请求的状态,如果状态是 2xx 或者 304 的话则代表返回正常。这个时 候我们就可以通过 response 中的数据来对页面进行更新了。 当对象的属性和监听函数设置完成后,最后我们调用 sent 方法来向服务器发起请求,可以传入参数作为发送的数据体。

同步和异步的区别?

解答:同步指的是当一个进程在执行某个请求的时候,如果这个请求需要等待一段时间才能返回,那么这个进程会一直等待下去,直到消息返 回为止再继续向下执行。 异步指的是当一个进程在执行某个请求的时候,如果这个请求需要等待一段时间才能返回,这个时候进程会继续往下执行,不会阻塞等 待消息的返回,当消息返回时系统再通知进程进行处理。

什么是浏览器的同源政策?

解答:我对浏览器的同源政策的理解是,一个域下的 js 脚本在未经允许的情况下,不能够访问另一个域的内容。这里的同源的指的是两个 域的协议、域名、端口号必须相同,否则则不属于同一个域。 同源政策主要限制了三个方面 第一个是当前域下的 js 脚本不能够访问其他域下的 cookie、localStorage 和 indexDB。 第二个是当前域下的 js 脚本不能够操作访问操作其他域下的 DOM。 第三个是当前域下 ajax 无法发送跨域请求。 同源政策的目的主要是为了保证用户的信息安全,它只是对 js 脚本的一种限制,并不是对浏览器的限制,对于一般的 img、或者 script 脚本请求都不会有跨域的限制,这是因为这些操作都不会通过响应结果来进行可能出现安全问题的操作。

如何解决跨域问题?

知识点:(1) 通过 jsonp 跨域 (2) document.domain + iframe 跨域 (3) location.hash + iframe (4) window.name + iframe 跨域 (5) postMessage 跨域 (6) 跨域资源共享(CORS) (7) nginx 代理跨域 (8) nodejs 中间件代理跨域 (9) WebSocket 协议跨域

简单说说你了解的进程与线程

进程和线程简单而基本靠谱的定义如下:

  1. 进程:程序的一次执行
  2. 线程:CPU的基本调度单位

*为什么 0.1 + 0.2 != 0.3?如何解决这个问题?

解答:当计算机计算 0.1+0.2 的时候,实际上计算的是这两个数字在计算机里所存储的二进制,0.1 和 0.2 在转换为二进制表示的时候 会出现位数无限循环的情况。js 中是以 64 位双精度格式来存储数字的,只有 53 位的有效数字,超过这个长度的位数会被截取掉 这样就造成了精度丢失的问题。这是第一个会造成精度丢失的地方。在对两个以 64 位双精度格式的数据进行计算的时候,首先会进 行对阶的处理,对阶指的是将阶码对齐,也就是将小数点的位置对齐后,再进行计算,一般是小阶向大阶对齐,因此小阶的数在对齐 的过程中,有效数字会向右移动,移动后超过有效位数的位会被截取掉,这是第二个可能会出现精度丢失的地方。当两个数据阶码对 齐后,进行相加运算后,得到的结果可能会超过 53 位有效数字,因此超过的位数也会被截取掉,这是可能发生精度丢失的第三个地 方。 对于这样的情况,我们可以将其转换为整数后再进行运算,运算后再转换为对应的小数,以这种方式来解决这个问题。 我们还可以将两个数相加的结果和右边相减,如果相减的结果小于一个极小数,那么我们就可以认定结果是相等的,这个极小数可以 使用 es6 的 Number.EPSILON

github.com/CavsZhouyou… 99题

vue 双向数据绑定原理?

www.cnblogs.com/kidney/p/60…

Object.defineProperty 介绍?

Object.defineProperty 函数一共有三个参数,第一个参数是需要定义属性的对象,第二个参数是需要定义的属性,第三个是该 属性描述符。 一个属性的描述符有四个属性,分别是 value 属性的值,writable 属性是否可写,enumerable 属性是否可枚举,configura ble 属性是否可配置修改。

使用 Object.defineProperty() 来进行数据劫持有什么缺点?

有一些对属性的操作,使用这种方法无法拦截,比如说通过下标方式修改数组数据或者给对象新增属性,vue 内部通过重写函数解决 了这个问题。在 Vue3.0 中已经不使用这种方式了,而是通过使用 Proxy 对对象进行代理,从而实现数据劫持。使用 Proxy 的 好处是它可以完美的监听到任何方式的数据改变,唯一的缺点是兼容性的问题,因为这是 ES6 的语法。

Vue 的各个生命阶段是什么?

Vue 组件间的参数传递方式?

Math.ceil 和 Math.floor

Math.ceil() === 向上取整,函数返回一个大于或等于给定数字的最小整数。 Math.floor() === 向下取整,函数返回一个小于或等于给定数字的最大整数。

*一个列表,假设有100000个数据,这个该怎么办?

我们需要思考的问题:该处理是否必须同步完成?数据是否必须按顺序完成? 解决办法: (1)将数据分页,利用分页的原理,每次服务器端只返回一定数目的数据,浏览器每次只对一部分进行加载。 (2)使用懒加载的方法,每次加载一部分数据,其余数据当需要使用时再去加载。 (3)使用数组分块技术,基本思路是为要处理的项目创建一个队列,然后设置定时器每过一段时间取出一部分数据,然后再使用定 时器取出下一个要处理的项目进行处理,接着再设置另一个定时器。

*使用闭包实现每隔一秒打印 1,2,3,4

使用闭包实现 for (var i = 0; i < 5; i++) { (function (i) { setTimeout(function() { console.log(i); }, i * 1000); })(i) } 使用 let 块级作用域 for(let i = 0; i < 5; i++){ setTimeout(function() { console.log(i); }, i * 1000); }

工具

*经常使用的 git 命令?

git init // 新建 git 代码库 git add // 添加指定文件到暂存区 git rm // 删除工作区文件,并且将这次删除放入暂存区 git commit -m [message] // 提交暂存区到仓库区 git branch // 列出所有分支 git checkout -b [branch] // 新建一个分支,并切换到该分支 git status // 显示有变更的文件

*git pull 和 git fetch 的区别

git fetch 只是将远程仓库的变化下载下来,并没有和本地分支合并。 git pull 会将远程仓库的变化下载下来,并和当前分支合并。

*git rebase 和 git merge 的区别

git merge 和 git merge 都是用于分支合并,关键在 commit 记录的处理上不同。 git merge 会新建一个新的 commit 对象,然后两个分支以前的 commit 记录都指向这个新 commit 记录。这种方法会 保留之前每个分支的 commit 历史。 git merge 会先找到两个分支的第一个共同的 commit 祖先记录,然后将提取当前分支这之后的所有 commit 记录,然后 将这个 commit 记录添加到目标分支的最新提交后面。经过这个合并后,两个分支合并后的 commit 记录就变为了线性的记 录了。

编码

js 如何实现数组去重?

代码块 function unique(array) { if (!Array.isArray(array) || array.length <= 1) return; ​ var result = []; ​ array.forEach(function (item) { if (result.indexOf(item) === -1) { result.push(item); } }) ​ return result; } ​ ​ function unique(array) { if (!Array.isArray(array) || array.length <= 1) return; ​ return [...new Set(array)]; } 如何将浮点数点左边的数每三位添加一个逗号,如12000000.11转化为『12,000,000.11』?

function format(number){ return number && number.replace(/(?!^)(?=(\d{3})+.)/g,",") }

实现 IndexOf 方法?

代码块 function indexFun(array, val) { if (!Array.isArray(array)) return; ​ let length = array.length; ​ for (let i = 0; i < length; i++) { if (array[i] === val) { return i; } } ​ return -1; }
手写 call、apply 及 bind 函数

代码块 call函数实现 ​ Function.prototype.myCall = function (context) { // 判断调用对象 if (typeof this !== "function") { console.error("type error"); } ​ // 获取参数 let args = [...arguments].slice(1), result = null; ​ // 判断 context 是否传入,如果未传入则设置为 window context = context || window; ​ // 将调用函数设为对象的方法 context.fn = this; ​ // 调用函数 result = context.fn(...args); ​ // 将属性删除 delete context.fn; ​ return result; } ​ ​ apply 函数实现 ​ Function.prototype.myApply = function (context) { // 判断调用对象是否为函数 if (typeof this !== "function") { throw new TypeError("Error"); } ​ let result = null; ​ // 判断 context 是否存在,如果未传入则为 window context = context || window; ​ // 将函数设为对象的方法 context.fn = this; ​ // 调用方法 if (arguments[1]) { result = context.fn(...arguments[1]); } else { result = context.fn(); } ​ // 将属性删除 delete context.fn; ​ return result; } ​ ​ bind 函数实现 ​ Function.prototype.myBind = function (context) { // 判断调用对象是否为函数 if (typeof this !== "function") { throw new TypeError("Error"); } ​ // 获取参数 var args = [...arguments].slice(1), fn = this; ​ return function Fn() { ​ // 根据调用方式,传入不同绑定值 return fn.apply(this instanceof Fn ? this : context, args.concat(...arguments)); } ​ } 算法

(树、排序、空间复杂度、时间复杂度相结合)

用3升,5升杯子怎么量出4升水?

(1)将 5 升杯子装满水,然后倒入 3 升杯子中,之后 5 升杯子还剩 2 升水。 (2)将 3 升杯子的水倒出,然后将 5 升杯子中的 2 升水倒入 3 升杯子中。 (3)将 5 升杯子装满水,然后向 3 升杯子中倒水,直到 3 升杯子装满为止,此时 5 升杯子中就还剩 4 升水。

有1到10这个10个数,去除2个并打乱次序,如何找出那两个数?

代码块 var c=[5,2,1,3,4,6,9,8]; //d的位置 var d=[1,2,3,4,5,6,7,8,9,10]; for(var i=0;i<10-2;i++){ d[c[i]-1]=1; } console.log(d) *求两个字符串的最大公共子串

输入示例:'abcdefg'、'abfg'

输出示例:‘ab’

代码块 function find (s1, s2) { if (s1.length < s2.length) { var s3 = s1; s1 = s2; s2 = s3; } var str = ''; var arr = []; for (var i = s2.length; i > 0; i--) { for (var j = 0; j <= s2.length - i; j++) {

str = s2.substr(j, i);

console.log(j, i, str); if (s1.indexOf(str) >= 0) { arr.push(str); } } if (arr.length > 0) {return arr;} } return ''; } 公共字子串一定是 <= Math.min(len1, len2),而且子串必定连续,且一定是a、b的子串。

平时如何学习前端知识

明确工作在北京,

询问候选人想问的问题

询问入职时间