1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 新版js进阶高频面试题

新版js进阶高频面试题

时间:2019-09-18 21:04:21

相关推荐

新版js进阶高频面试题

01-[-10-19]

目录

01-[-10-19]一、移动web1.1 请说下初始化CSS样式的意义1.2 谈谈你对HTML语义化的理解?1.3 请说下如何居中一个div?1.4 请说下px/em/rem这三个单位有什么区别?1.5 你说下rem布局的原理和思路吧?1.6 通过CSS如何写一个三角形?1.7 如何实现两侧固定中间自适应的布局?1.8 你知道BFC吗?二、JS基础2.1 说下typeof返回的数据类型2.2 请说下转换为false的情况有哪些?2.3 两个等号和三个等号的区别是什么?2.4 请说说你对作用域链的理解?2.5 简单数据类型与复杂数据类型在内存上存储有什么区别?三、webapi3.1 请说下什么是重绘和重排(回流)?他们的区别是什么?3.2 说说this的指向问题吧?3.3 事件流分为哪两个阶段?3.4 事件委托的实现原理??3.5 你能说说怎么理解事件循环机制的?四、JS高级1、什么是深/浅拷贝2、如何用递归实现深拷贝?3、描述下垃圾回收机制?4、对闭包是怎么理解的?5、什么是原型对象和原型链6、原型链有什么意义?7、call、apply和bind的区别8、怎么理解函数的防抖和节流五、ajax5.1、请说出宏任务与微任务,在事件循环机制中是如何执行的?5.2、http和https的区别5.3、get 和post的区别5.4、在地址栏输入网址,到数据返回的过程是什么?5.5、怎么理解三次握手

(持续更新中)

一、移动web

1.1 请说下初始化CSS样式的意义

答: 1、浏览器差异:因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对CSS初始化往往会出现浏览器之间的页面显示差异。

2、提高编码质量:初始化CSS可以节约网页代码,节约网页下载时间;还会使得我们开发网页内容时更加方便简洁,不用考虑很多。如果不初始化,整个页面做完会很糟糕,重复的css样式很多。

常见写法:常见写法: ①:最简单的初始化方法就是: * {padding: 0; margin: 0;} 。这样一个通用符在编写代码的时候是快,但这样写的话,他会把所有的标签都初始化一遍,这样就增加了网站运行的负载,会使网站加载过慢。

②:最好的做法是针对常用的标签进行初始化即可。 参考淘宝、腾讯等网站的css初始化:/css/1113842.html

1.2 谈谈你对HTML语义化的理解?

答:

根据页面的结构,选择合适的语义化标签,用正确的标签做正确的布局,同时有利于浏览器、搜索引擎的解析。

追问:为什么要语义化

1、HTML语义化让页面的内容结构化,结构更清晰,便于让浏览器、搜索引擎解析

2、即使在没有样式CSS情况下也以一种文档格式显示,并且是易于阅读的

3、搜索引擎也依赖于HTML标记来确定上下文和各个关键字的权重,利于SEO

4、使阅读源代码的人更容易将网站分块,便于阅读维护理解

追问:平时你写HTML代码还有那些注意事项? 1)尽可能少的使用无语义的标签div和span 2)在语义不明显时,既可以使用div或者p时,尽量用p,因为p在默认情况下有上下间距,对兼容特殊终端有利 3)不要使用纯样式标签,如:b、font、u等,改用CSS设置 4)需要强调的文本,可以包含在strong或者em标签中(浏览器预设样式,能用css指定就不用他们),strong默认样式是加粗(不要用b),em是斜体(不用i) 5)使用表格时,标题要用caption,表头用thead,主体部分用tbody包围,尾部用tfoot包围。表头和单元格要区分开,表头用th,单元格用td 6)表单域要用fieldset标签抱起来,并用legend标签说明表单的用途 7)每个input标签对应的说明文本都需要使用label标签,并且通过为input设置id属性,在label标签中设置for=someId来让说明文本和相对应的input关联起来

追问:你知道有哪些HTML5新增的语义标签? article(定义文章)、aside(定义文章的侧边栏)、figure(一组媒体对象以及文字)、figurecaption(定义figure的标题)、footer(定义页脚)、header(定义页眉)、nav(定义导航栏)、section(定义文档中的区段)、time(定义日期和时间)、dialog(定义一个对话框)

1.3 请说下如何居中一个div?

答: 方法有很多,我大概记得以下5~6种吧。(回答可以直接说标题即可 如果非要说代码,也是说文字)

方法一: 利用定位

方法二:利用 margin:auto;

方法三: 利用 display:table-cell

方法四: 利用 display: flex;设置垂直水平都居中

方法五: 计算父盒子与子盒子的空间距离(这跟方法一是一个道理) (不够好:自己算)

方法六: 利用 transform

1.4 请说下px/em/rem这三个单位有什么区别?

答: ①: px 是绝对单位,而 em 和 rem 是相对单位。

②: em相对于当前元素内文本的字体大小,找不到就找父亲的文字大小,而 rem是相对的HTML 根元素文字大小

③: px适合于固定文字大小, em经常用于比如段落首行缩进等, rem在后期移动端开发经常用于做适配。

1.5 你说下rem布局的原理和思路吧?

答:

rem布局实现目的: 等比缩放

1、元素所有属性 只要px单位—>rem单位

2、rem单位非常神奇,背后 基准值会变。

3、基准值取决于根元素字号大小,屏幕变化导致根元素字号大小变;

4、实现原理:给window注册resize。当变化内部函数设置 根元素字号大小 = 为当前屏幕宽度 / 固定数值 通常为10

1.6 通过CSS如何写一个三角形?

答: 利用css边框属性就可以得到三角形。

边框是梯形的,如果盒子没有宽高,则会变成三角形,设置三个角透明色,其中一个角给颜色,就能得到三角形了

1.7 如何实现两侧固定中间自适应的布局?

答:圣杯布局

flex布局: 大盒子里面包含左中右三个小盒子,父盒子利用display:flex。两侧直接写固定宽度,中间盒子给flex:1 即可。

传统方案:父亲设置 box-sizing:border-box CSS3盒子模型,设置左右padding, 子元素三个:左右侧绝对定位宽度(正好是设置padding)高度同父亲 。 中间:设置100% 100%高

1.8 你知道BFC吗?

答: ①:BFC(Block Formatting Context),即块级格式化上下文,它是页面中的一块渲染区域,并且有一套属于自己的渲染规则,BFC目的是形成一个相对于外界完全独立的空间,让内部的子元素不会影响到外部的元素 ②:触发BFC的条件

●根元素,即HTML元素

●浮动元素:float值为left、right

●overflow值不为 visible,为 auto、scroll、hidden

●display的值为inline-block、inltable-cell、table-caption、table、inline-table、flex、inline-flex、grid、inline-grid

●position的值为absolute或fixed

③:BFC的主要使用场景:

●防止margin重叠(塌陷)。 比如给父级添加overflow,就触发了BFC, 还有子元素浮动,不会触发外边距塌陷原因也是因为触发了BFC

●清除内部浮动。 同样,清除浮动方法中有个overflow:hidden 方法

二、JS基础

2.1 说下typeof返回的数据类型

回答: ①:简单数据类型直接返回对应的英文,比如:number string boolean undefined 等,特殊情况,null 返回 object

②:复杂数据类型返回 object,函数返回的是 function fn(){…} typeof fn

2.2 请说下转换为false的情况有哪些?

答: 一共七种,

自动转换为false的有: 0 、 “”、 null、 false、 NaN、 undefined、还有不成立的表达式

2.3 两个等号和三个等号的区别是什么?

回答: == 表示是相等,只比较内容,类型不同,会隐式转换为同类型,进行比较!

=== 表示是全等,不仅比较内容,也比较类型!如果类型不同,直接false

2.4 请说说你对作用域链的理解?

回答: ①:JavaScript中的作用域分为全局作用域、局部作用域,多个嵌套的作用域形成作用域链。 ②:作用域链:为了内部寻找一个变量的查找规则,

●当在某个作用域中查找变量时,如果当前作用域没有找到,则向上层作用域查找,上层没有声明,继续向上层查找,一直找到全局作用域。

●找的过程中,找到则使用该变量,没有找到则报错。

2.5 简单数据类型与复杂数据类型在内存上存储有什么区别?

回答: ①:基本类型主要为以下6种:Number、String、Boolean、Undefined、null、symbol 基本数据类型的值存储在 栈中

②:引用类型 Object、Array、Function 引用类型的值存储于 堆中

三、webapi

3.1 请说下什么是重绘和重排(回流)?他们的区别是什么?

●第一次渲染

○html结构 解析为 dom树

○css样式 解析为 样式规则

○dom树 和 样式规则 匹配下,生成渲染树!

○接下来就是重排:根据渲染树,得到每个盒子的几何信息(大小位置)

○最后就是重绘:根据得到几何信息,进行页面绘制!

●后续操作:

○如果进行操作有可能导致页面某些元素几何信息变化,导致回流(重排)!

○进行操作不是改变几何信息,比如颜色变了,只需要重绘!

●最后:重绘不一定引起回流(重排),而回流(重排)一定会引起重绘

重排: 也叫做回流,当DOM元素影响了元素的几何属性(例如宽和高),浏览器需要重新计算元素的几何属性,同样其它元素的几何属性和位置也会因此受到影响。浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树。这个过程称为“重排”。

重绘: 完成重排后,浏览器会重新绘制受影响的部分到屏幕上中,该过程称为“重绘”。

总结:

当我们改变DOM的大小,增加删除都会导致重排,当给DOM元素改变颜色的时候,会导致重绘,重排一定会重绘,重绘不会重排。重排会影响性能,所以我们尽快能的减少重排的操作(这句话是重点)

3.2 说说this的指向问题吧?

回答: 谁调用执行谁!

this是个关键字,它的指向和函数的调用方式有关, 初步的理解就是,this指向所在函数的调用者。

1、 以函数形式调用时, this 永远都是 window 。

2、 以方法的形式调用时, this 是调用方法的对象。

3、 以构造函数的形式调用时, this 是新创建的那个对象 。

4、 使用 call 和 apply 调用时, this 是指定的那个对象。

5、 箭头函数: 箭头函数的 this 按照普通变量对待。比如把他当做 x 变量即可,然后按照作用域链找就行了。

6、全局中的this是window 7、事件处理函数,如果是普通的function函数,则this指向事件源。

3.3 事件流分为哪两个阶段?

事件流是指事件传播的顺序,由事件捕获 => 目标事件 => 事件冒泡 所以事件流分为捕获和冒泡两个阶段。

3.4 事件委托的实现原理??

答:

事件委托主要利用事件冒泡特性来实现的 事件委托(事件委派)主要使用场景:如果有多个子元素需要注册同一类事件,不管这些子元素是已经存在的,还是动态生成的,都可以把事件注册给父元素!因为触发子元素,就会将事件冒泡到其父元素上,利用这个特点提高了性能。

好处:提高了性能,节省内存

缺点:若触发不同的子元素执行不同的代码,那么这些代码全部维护在一个函数内部,不便于代码维护

追问:如果获取当前触发的dom节点?

答:使用 e.target 获取当前触发事件的元素。

3.5 你能说说怎么理解事件循环机制的?

答:

0、JS语言设计的时候:就是单线程!(某个时间点,代码程序只能做一件事!)(可以不说:带来的问题:代码任务需要排队,前面程序没有执行完,后面程序不会执行!给用户加载阻塞感受!)JS设计了同步 与 异步概念!下面具体描述:

1、JS代码执行之前会被浏览器解析:

2、浏览器解析JS代码过程中:把同步代码留在【主线程】上进行执行,把异步代码 放在 【宿主环境】中

3、宿主环境中的回调函数,到了该调用时候,不是直接放到【主线程】上进行执行,而是放到【任务队列】里面

4、事件循环机制功能:等待【主线程】同步代码执行完毕后,去【任务队列】调取任务,拿到【主线程】上进行执行,执行完毕后,会继续去【任务队列】调取任务

四、JS高级

1、什么是深/浅拷贝

浅拷贝: 拷贝对象的一层属性,如果对象里面还有对象,拷贝的是地址, 两者之间修改会有影响,适用于对象里面属性的值是简单数据类型的.

深拷贝: 拷贝对象的多层属性,如果对象里面还有对象,会继续拷贝,使用递归去实现.

2、如何用递归实现深拷贝?

其他方式:

lodash:_.cloneDeep(被拷贝的对象)

JSON.parse(JSON.stringify(被拷贝的对象))

3、描述下垃圾回收机制?

首先:垃圾回收机制内部算法:引用计数 和 标记清除

接下来:

●引用计数:把堆上对象能够访问次数记下来,如果发现某个对象计数为0,算法认为没有变量访问这个对象。该对象所占空间,判定是垃圾,进行回收!但是:如果两个对象相互引用,各自计数永远不会为0,不会判定为是垃圾,不会回收!所以:主流浏览器不再使用该算法!

●标记清除:核心就是 从 使用对象次数 到 无法到达对象;只要是堆上对象无法访问,哪怕是对象相互引用,但是无法访问,算法对该对象标记为垃圾空间!

4、对闭包是怎么理解的?

答:

●基本形式:两个嵌套关系的函数,内部函数可以访问外部函数定义的局部变量,那么该变量与内部函数就构造了闭包的形式

●优点:形成私有空间,避免全局变量的污染

●缺点:持久化内存,导致内存泄露

●解决:

○1、尽快避免函数的嵌套,以及变量的引用

○2、执行完的变量,可以赋值null,触发垃圾回收机制,进行回收释放内存

5、什么是原型对象和原型链

答:

原型对象:每个构造函数都有prototype属性,这个属性的值是个对象,称之为原型对象!

原型链:对象都有__proto__属性,这个属性指向它的原型对象,原型对象也是对象,也有__proto__属性,指向原型对象的原型对象,这样一层一层形成的链式结构称为原型链.

6、原型链有什么意义?

总得来说:给实例化对象上调用方法或使用某个属性,提供查询机制!

具体查询:

先在实例化对象本身上去找该方法!

如果没有,去实例化对象的__proto__(原型对象上去找)

如果当前原型对象上还没有该方法,继续往原型对象上的原型对象上去找

如果还是没有找到,报错 对象xxx is not function

7、call、apply和bind的区别

答:

1、call和apply方法都可以调用函数,方法内的第一个参数可以修改this的指向

2、call方法可以有多个参数,除了第一个参数,其他参数作为实参传递给函数;apply方法最多有2个参数,第二个参数是个数组或伪数组,数组里面的每一项作为实参传递给函数

3. bind方法不能调用函数,它会创建一个副本函数,并且绑定新函数的this指向bind返回的新的函数

8、怎么理解函数的防抖和节流

防抖:就是指触发事件后,在n秒后对应的函数会执行!如果在n秒中又触发了事件,则会重新计算函数执行时间。

节流:就是指连续触发事件,如果上一次触发的对应的执行函数没有执行完成,下一次触发是不会引起对应函数的执行的。

五、ajax

5.1、请说出宏任务与微任务,在事件循环机制中是如何执行的?

答:

1、代码:分为【宏任务】与【微任务代码】

【宏任务】:主代码块、定时器代码、dom节点事件触发代码、ajax代码 ;(主代码块: script标签包着这些代码)

【微任务】 promise实例对象的.then(回调函数)

2、宏任务与微任务都会去【宿主环境】。

3、这些代码里面回调函数到了要执行点的时候,不是直接去【主线程】,而是去【任务队列】。到了【任务队列】分为两个队列【宏任务队列】与【微任务队列】

4、最一开始【事件循环机制】先执行 【主代码块】,又会分为:

异步代码:在执行的过程中又分出来【宏任务】与【微任务】到【宿主环境】,然后各自排队到任务队列里的【宏任务队列】与【微任务队列】

同步代码:分到主线程上,就继续执行。

5、执行完第一个主代码里面同步代码后,【事件循环机制】会先把【微任务队列】里面所有函数执行完成后,才去执行【宏任务队列】的下一个的函数。

简叙:任务队列里执行函数【微任务队列】比【宏任务队列】优先。

例题1:

<script>console.log(1);setTimeout(() => {console.log(2);}, 0)console.log(3);</script><script>console.log(4);setTimeout(() => {console.log(5);}, 0)console.log(6);</script>

例题2:

console.log(1)setTimeout(function() {console.log(2)}, 0)const p = new Promise((resolve, reject) => {console.log(3)resolve(1000) // 标记为成功console.log(4)})p.then(data => {console.log(data)})console.log(5)

例题三:

new Promise((resolve, reject) => {resolve(1)new Promise((resolve, reject) => {resolve(2)}).then(data => {console.log(data)})}).then(data => {console.log(data)})console.log(3)

例题四:

setTimeout(() => {console.log(1)}, 0)new Promise((resolve, reject) => {console.log(2)resolve('p1')new Promise((resolve, reject) => {console.log(3)setTimeout(() => {resolve('setTimeout2')console.log(4)}, 0)resolve('p2')}).then(data => {console.log(data)})setTimeout(() => {resolve('setTimeout1')console.log(5)}, 0)}).then(data => {console.log(data)})console.log(6)

例题五:

<script>console.log(1);async function fnOne() {console.log(2);await fnTwo(); // 右结合先执行右侧的代码, 然后等待console.log(3);}async function fnTwo() {console.log(4);}fnOne();setTimeout(() => {console.log(5);}, 2000);let p = new Promise((resolve, reject) => {// new Promise()里的函数体会马上执行所有代码console.log(6);resolve();console.log(7);})setTimeout(() => {console.log(8)}, 0)p.then(() => {console.log(9);})console.log(10);</script><script>console.log(11);setTimeout(() => {console.log(12);let p = new Promise((resolve) => {resolve(13);})p.then(res => {console.log(res);})console.log(15);}, 0)console.log(14);</script>

例题六:(今日头条面试题)

async function async1 () {console.log('async1 start');await async2();console.log('async1 end');}async function async2 () {console.log('async2');}console.log('script start');setTimeout(function () {console.log('setTimeout');}, 0);async1();new Promise(function (resolve) {console.log('promise1');resolve();}).then(function () {console.log('promise2');});console.log('script end');

5.2、http和https的区别

答:

1.https协议需要到CA申请证书,一般免费证书较少,因而需要一定费用。

2.http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl/tls加密传输协议。

3.http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

4.http的连接很简单,是无状态的;HTTPS协议是由SSL/TLS+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

5.3、get 和post的区别

答:

get

在url后面拼接参数,只能以文本的形式传递数据传递的数据量小,4KB左右安全性低, 会将数据显示在地址栏速度快,通常用于安全性要求不高的请求会缓存数据

post

安全性比较高传递数据量大,请求对数据长度没有要求请求不会被缓存,也不会保留在浏览器历史记录里

5.4、在地址栏输入网址,到数据返回的过程是什么?

输入url地址后,首先进行DNS解析,将相应的域名解析为IP地址。根据IP地址去寻找相应的服务器。与服务器进行TCP的三次握手,建立连接。客户端发送请求,找到相应的资源库。客户端拿到数据,进行相应的渲染。

5.5、怎么理解三次握手

答:

第一次握手:建立连接时,客户端发送syn包到服务器,等待服务器确认。

第二次握手:服务器收到syn包,必须确认客户的SYN,同时自己也发送一个SYN包(syn=y)到客户端

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

通俗:

第一次:客户端告诉服务器,我有个诉求,想要向你请求数据,你能听见么?

第二次:服务器告诉客户端,收到你的诉求,允许请求数据,你能听见么?

第三次:客户端告诉服务器,OK收到。

6、怎么理解四次挥手

答:

第一次分手:客户端向服务器发送一个FIN报文段;此时,客户端进入FIN_WAIT_1状态;这表示没有数据要发送给服务器了。

第二次分手:服务器 收到 客户端 发送的FIN报文段,向 客户端 回一个ACK报文段,主机1进入FIN_WAIT_2状态;服务器告诉 客户端,我知道你的诉求了,也“同意”你的关闭请求,但是具体什么时候关闭,等我通知;

第三次分手:服务器 向 客户端 发送FIN报文段,说可以正式关闭连接了,同时 服务器 进入LAST_ACK状态。

第四次分手:客户端 收到 服务器 发送的FIN报文段,向 服务器 发送ACK报文段,然后 客户端 进入TIME_WAIT状态;服务器 收到 客户端的ACK报文段以后,服务器就正式关闭连接;此时,客户端等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,客户端也可以正式关闭连接了。

通俗:

第一次分手:客户端告诉服务器,我有个诉求,我这边没有数据了,我要准备关闭了。

第二次分手:服务器收到信息后,回复:我收到你的诉求了,你可以进行准备着,但是何时正式关闭,等我通知。

第三次分手:服务器 给 客户端发信:你现在准备正式关闭了。

第四次分手:客户端 给 服务器发信:OK呢,我知道了。

(服务器:收到信息后,服务器正式关闭了)

(客户端:???等了一会,这家伙没有说就下线了,嗯~真的关了,好吧,我也是正式关了。)

(持续更新中~~~~)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。