前端开发面试题及答案(前端面试题整理(一))

本文目录
前端面试题整理(一)
进程是CPU资源分配的最小单位,线程是CPU调度的最小单位
其中GUI渲染线程和JS引擎是无法同时工作的
默认情况下, TCP 连接会启用延迟传送算法 (Nagle 算法), 在数据发送之前缓存他们. 如果短时间有多个数据发送, 会缓冲到一起作一次发送 (缓冲大小见 socket.bufferSize), 这样可以减少 IO 消耗提高性能.
如果是传输文件的话, 那么根本不用处理粘包的问题, 来一个包拼一个包就好了. 但是如果是多条消息, 或者是别的用途的数据那么就需要处理粘包.
可以参见网上流传比较广的一个例子, 连续调用两次 send 分别发送两段数据 data1 和 data2, 在接收端有以下几种常见的情况:
A. 先接收到 data1, 然后接收到 data2 .
B. 先接收到 data1 的部分数据, 然后接收到 data1 余下的部分以及 data2 的全部.
C. 先接收到了 data1 的全部数据和 data2 的部分数据, 然后接收到了 data2 的余下的数据.
D. 一次性接收到了 data1 和 data2 的全部数据.
其中的 BCD 就是我们常见的粘包的情况. 而对于处理粘包的问题, 常见的解决方案有:
多次发送之前间隔一个等待时间
关闭 Nagle 算法
进行封包/拆包
通过滑动窗口协议(连续ARQ协议)实现,保证了分组无差错、有序接收、流量控制。接收方返回的ACK中会包含自己的接收窗口的大小,并且利用大小来控制发送方的数据发送。
当发送者收到了一个窗口为0的应答,发送者便停止发送,等待接收者的下一个应答。如果这个窗口不为0的应答在传输过程中丢失,发送者一直等待,接收者以为发送者收到该应答,等待接收新数据,这样双方就相互等待,从而产生死锁
TCP使用了持续计时器。每当发送者收到一个0窗口的应答后就启动该计时器。计时器到时便主动发送报文询问接收者的窗口大小。若接收者仍然返回0窗口,则重置该计时器继续等待;若窗口不为0,则标识应答报文丢失了,此时重置发送窗口开始发送,这样就避免了死锁的产生
拥塞控制是作用于网络的,防止网络负载过大,常用的方法:1.慢启动、拥塞避免 2.快重传、快恢复。流量控制是作用于接收者的,控制发送者的发送速度使接收者来得及接收,防止分组丢失
发送方维持一个叫做拥塞窗口CWnd的状态变量,控制着传输速度,TCP开始发送报文时CWnd=1。一个传输轮次所经历的时间就是往返时间RTT,每经过一个RTT并且按时收到确认,就将拥塞窗口CWnd加倍。还有一个叫慢启动门限ssthresh的状态变量,当CWnd《ssthresh时,使用慢启动,当CWnd》=ssthresh改用拥塞避免算法
每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1而不是加倍。无论在慢启动阶段还是拥塞避免阶段,只要发送方没有按时收到确认,就把慢启动门限设置为出现拥塞时的拥塞窗口cwnd的一半(但不小于2)。然后把拥塞窗口cwnd重置为1,执行慢启动算法
接收方收到一个失序的报文段后就立刻发出重复确认而不是等到自己发送数据时捎带确认。只要发送方一连收到三个重复确认就立即重传对方尚未收到的报文段,而不是等待重传计时器到期
当发送方连续收到三个重复确认时,把慢启动门限ssthresh减半,但是并不执行慢开始算法,而是将拥塞窗口cwnd设置为ssthresh减半后的值,直接执行拥塞避免算法。快重传配合快恢复的TCP Reno版本是目前使用最广的版本。
帧:HTTP/2 数据通信的最小单位消息:指 HTTP/2 中逻辑上的 HTTP 消息。例如请求和响应等,消息由一个或多个帧组成。
流:存在于连接中的一个虚拟通道。流可以承载双向消息,每个流都有一个唯一的整数ID
HTTP/1.x会在请求和响应中中重复地携带不常改变的、冗长的头部数据,给网络带来额外的负担。
服务端可以在发送页面HTML时主动推送其它资源,而不用等到浏览器解析到相应位置,发起请求再响应。例如服务端可以主动把JS和CSS文件推送给客户端,而不需要客户端解析HTML时再发送这些请求。
服务端可以主动推送,客户端也有权利选择是否接收。如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送RST_STREAM帧来拒收。主动推送也遵守同源策略,服务器不会随便推送第三方资源给客户端。
HTTP 1.x 中,如果想并发多个请求,必须使用多个 TCP 链接,且浏览器为了控制资源,还会对单个域名有 6-8个的TCP链接请求限制。
HTTP2中:
同域名下所有通信都在单个连接上完成。
单个连接可以承载任意数量的双向数据流。
数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装
前端面试与进阶指南
从输入URL到页面加载的过程?如何由一道题完善自己的前端知识体系!
前端笔试面试题总结(二)
A. null
B.
C.
D.
解析:
注:members被赋值的是person的指针;
正确答案:D
A. f foo(){ foo =10; console.log(foo)}
B. 1
C. 10
D. undefined
解析:
具名的匿名函数,函数名默认指向其本身,且具有只读属性,函数会被当作函数表达式而不是一个标准的函数声明来处理,函数表达式意味着函数被直接绑定在作用域中,意味着foo只能在被自己代表的位置被调用,不会污染全局作用域。
正确答案:A
解析:
正确答案: 30 24
解析:
正确答案:undefined 10 20
A. { name: "Lydia",age: 21} ,
B. { name: "Lydia",age: 21} ,
C. { name: "Lydia"} ,
D. { name: "Lydia"} ,
解析:
注: Object.defineProperty 是ES5提供的一种给对象定义属性的方式,定义的属性默认不可以枚举、遍历,不可以删除;可以使用set、get,定义属性时触发get,修改属性值时触发set,利用其可以实现数据双向绑定。
Object.keys 返回的是数组,又因 Object.defineProperty 定义的属性默认不可以枚举、遍历,所以只能返回对象的第一个关键字;如果想要实现遍历,可以利用 enumerable:true 实现遍历,如果想要修改或删除,可以利用 configurable:true 实现。
正确答案:B
A. "{"level":19,"health":90}"
B. "{"username": "xiao ming"}"
C. ""
D. "{"username":"xiao ming","level":19,"health":90}"
解析:
JSON.stringify(value,replacer) 方法将一个 JavaScript 对象或值转换为 JSON 字符串,如果指定了一个 replacer 函数,则可以选择性地替换值,或者指定的 replacer 是数组,则可选择性地仅包含数组指定的属性。
正确答案:A
A. 20 , 40 , 80 , 160
B. 20 , 40 , 20 , 40
C. 20 , 20 , 20 , 40
D. NaN , NaN , 20 , 40
解析:
正确答案:C
A. Calculated! 20 Calculated! 20 Calculated! 20
B. Calculated! 20 From cache! 20 Calculated! 20
C. Calculated! 20 From cache! 20 Form cache! 20
D. Calculated! 20 From cache! 20 Error
解析:
注:闭包函数定义: 当一个函数的返回值是另外一个函数,而返回的那个函数如果调用了其父函数内部的其它变量,如果返回的这个函数在外部被执行,就产生了闭包。
表现形式:使函数外部能够调用函数内部定义的变量。
正确答案:C
A.
B. 2
C. true
D. undefined
解析:
注:push()方法的返回值:把指定的值添加到数组后的新长度
正确答案:B
A. "I made it!"
B. Promise {《resolved》: "I made it!"}
C. Promise {《pending》}
D. undefined
解析:
注:promise ES6语法中的异步操作的API,每一个promise包含三种状态 pending(挂起)、 resolve(成功)、 reject(失败), 而在每一个promise对象包含then 和 catch两个方法,then方法接收一个函数,用于处理resolve成功方法,而catch方法接收一个函数,用于处理reject失败的方法。
正确答案:C
有哪些经典的前端开发面试题及答案解析
行元素与块元素的区别;
如何清除浮动;
定位方式当中,absolute与fixed、relative的区别;
事件的兼容问题;
Ajax是什么;
如何优化你的页面;
响应式布局是什么等等。
经典的前端面试题至少有近百道,在这里也没办法全部给你列出来,你可以看看这个(小-程序),里面有好几百道面试真题,也有比较好的答案解析。
前端经典面试题(包含JS、CSS、React、浏览器等)
防抖
节流
误区:我们经常说get请求参数的大小存在限制,而post请求的参数大小是无限制的。
实际上HTTP 协议从未规定 GET/POST 的请求长度限制是多少。对get请求参数的限制是来源与浏览器或web服务器,浏览器或web服务器限制了url的长度。为了明确这个概念,我们必须再次强调下面几点:
补充补充一个get和post在缓存方面的区别:
可从IIFE、AMD、CMD、CommonJS、UMD、webpack(require.ensure)、ES Module、
vue和react都是采用diff算法来对比新旧虚拟节点,从而更新节点。在vue的diff函数中(建议先了解一下diff算法过程)。在交叉对比中,当新节点跟旧节点 头尾交叉对比 没有结果时,会根据新节点的key去对比旧节点数组中的key,从而找到相应旧节点(这里对应的是一个key =》 index 的map映射)。如果没找到就认为是一个新增节点。而如果没有key,那么就会采用遍历查找的方式去找到对应的旧节点。一种一个map映射,另一种是遍历查找。相比而言。map映射的速度更快。vue部分源码如下:
创建map函数
遍历寻找
在React中, 如果是由React引发的事件处理(比如通过onClick引发的事件处理),调用setState不会同步更新this.state,除此之外的setState调用会同步执行this.state 。所谓“除此之外”,指的是绕过React通过addEventListener直接添加的事件处理函数,还有通过setTimeout/setInterval产生的异步调用。
**原因:**在React的setState函数实现中,会根据一个变量isBatchingUpdates判断是直接更新this.state还是放到队列中回头再说,而isBatchingUpdates默认是false,也就表示setState会同步更新this.state,但是, 有一个函数batchedUpdates,这个函数会把isBatchingUpdates修改为true,而当React在调用事件处理函数之前就会调用这个batchedUpdates,造成的后果,就是由React控制的事件处理过程setState不会同步更新this.state 。
虚拟dom相当于在js和真实dom中间加了一个缓存,利用dom diff算法避免了没有必要的dom操作,从而提高性能。
具体实现步骤如下:
用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中
当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异
把2所记录的差异应用到步骤1所构建的真正的DOM树上,视图就更新了。
结构:display:none: 会让元素完全从渲染树中消失,渲染的时候不占据任何空间, 不能点击, visibility: hidden:不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,不能点击 opacity: 0: 不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,可以点击
继承:display: none:是非继承属性,子孙节点消失由于元素从渲染树消失造成,通过修改子孙节点属性无法显示。visibility: hidden:是继承属性,子孙节点消失由于继承了hidden,通过设置visibility: visible;可以让子孙节点显式。
性能:displaynone : 修改元素会造成文档回流,读屏器不会读取display: none元素内容,性能消耗较大 visibility:hidden: 修改元素只会造成本元素的重绘,性能消耗较少读屏器读取visibility: hidden元素内容 opacity: 0 :修改元素会造成重绘,性能消耗较少
联系:它们都能让元素不可见
常用的一般为三种 .clearfix , clear:both , overflow:hidden ;
比较好是 .clearfix ,伪元素万金油版本,后两者有局限性.
clear:both :若是用在同一个容器内相邻元素上,那是贼好的,有时候在容器外就有些问题了, 比如相邻容器的包裹层元素塌陷
overflow:hidden :这种若是用在同个容器内,可以形成 BFC 避免浮动造成的元素塌陷
概念:将多个小图片拼接到一个图片中。通过 background-position 和元素尺寸调节需要显示的背景图案。
优点:
缺点:
block 元素特点:
1.处于常规流中时,如果 width 没有设置,会自动填充满父容器 2.可以应用 margin/padding 3.在没有设置高度的情况下会扩展高度以包含常规流中的子元素 4.处于常规流中时布局时在前后元素位置之间(独占一个水平空间) 5.忽略 vertical-align
inline 元素特点
1.水平方向上根据 direction 依次布局
2.不会在元素前后进行换行
3.受 white-space 控制
4. margin/padding 在竖直方向上无效,水平方向上有效
5. width/height 属性对非替换行内元素无效,宽度由元素内容决定
6.非替换行内元素的行框高由 line-height 确定,替换行内元素的行框高由 height , margin , padding , border 决定 7.浮动或绝对定位时会转换为 block 8. vertical-align 属性生效
GIF :
JPEG :
PNG :
七种数据类型
(ES6之前)其中5种为基本类型: string , number , boolean , null , undefined ,
ES6出来的 Symbol 也是原始数据类型 ,表示独一无二的值
Object 为引用类型(范围挺大),也包括数组、函数,
输出结果是:
工厂模式
简单的工厂模式可以理解为解决多个相似的问题;
单例模式
只能被实例化(构造函数给实例添加属性与方法)一次
沙箱模式
将一些函数放到自执行函数里面,但要用闭包暴露接口,用变量接收暴露的接口,再调用里面的值,否则无法使用里面的值
发布者订阅模式
就例如如我们关注了某一个公众号,然后他对应的有新的消息就会给你推送,
代码实现逻辑是用数组存贮订阅者, 发布者回调函数里面通知的方式是遍历订阅者数组,并将发布者内容传入订阅者数组
1.字面量
2.Object构造函数创建
3.使用工厂模式创建对象
4.使用构造函数创建对象
HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件onclick、页面的滚动事件onscroll等等,可以向文档或者文档中的元素添加事件侦听器来预订事件。想要知道这些事件是在什么时候进行调用的,就需要了解一下“事件流”的概念。
什么是事件流:事件流描述的是从页面中接收事件的顺序,DOM2级事件流包括下面几个阶段。
addEventListener : addEventListener 是DOM2 级事件新增的指定事件处理程序的操作,这个方法接收3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。
IE只支持事件冒泡 。
获取一个对象的原型,在chrome中可以通过__proto__的形式,或者在ES6中可以通过Object.getPrototypeOf的形式。
那么Function.proto是什么么?也就是说Function由什么对象继承而来,我们来做如下判别。
我们发现Function的原型也是Function。
我们用图可以来明确这个关系:
这里来举个栗子,以 Object 为例,我们常用的 Object 便是一个构造函数,因此我们可以通过它构建实例。
则此时, 实例为instance , 构造函数为Object ,我们知道,构造函数拥有一个 prototype 的属性指向原型,因此原型为:
这里我们可以来看出三者的关系:
在 JS 中,继承通常指的便是 原型链继承 ,也就是通过指定原型,并可以通过原型链继承原型上的属性或者方法。
在函数式编程中,函数是一等公民。那么函数柯里化是怎样的呢?
函数柯里化指的是将能够接收多个参数的函数转化为接收单一参数的函数,并且返回接收余下参数且返回结果的新函数的技术。
函数柯里化的主要作用和特点就是参数复用、提前返回和延迟执行。
在一个函数中,首先填充几个参数,然后再返回一个新的函数的技术,称为函数的柯里化。通常可用于在不侵入函数的前提下,为函数 预置通用参数 ,供多次重复调用。
call 和 apply 都是为了解决改变 this 的指向。作用都是相同的,只是传参的方式不同。
除了第一个参数外, call 可以接收一个参数列表, apply 只接受一个参数数组。
bind 和其他两个方法作用也是一致的,只是该方法会返回一个函数。并且我们可以通过 bind 实现柯里化。
如何实现一个 bind 函数
对于实现以下几个函数,可以从几个方面思考
如何实现一个call函数
如何实现一个apply函数
箭头函数其实是没有 this 的,这个函数中的 this 只取决于他外面的第一个不是箭头函数的函数的 this 。在这个例子中,因为调用 a 符合前面代码中的第一个情况,所以 this 是 window 。并且 this 一旦绑定了上下文,就不会被任何代码改变。
在函数中,我们首先使用 var 关键字声明了 name 变量。这意味着变量在创建阶段会被提升( JavaScript 会在创建变量创建阶段为其分配内存空间),默认值为 undefined ,直到我们实际执行到使用该变量的行。我们还没有为 name 变量赋值,所以它仍然保持 undefined 的值。
使用 let 关键字(和 const )声明的变量也会存在变量提升,但与 var 不同,初始化没有被提升。在我们声明(初始化)它们之前,它们是不可访问的。这被称为“暂时死区”。当我们在声明变量之前尝试访问变量时, JavaScript 会抛出一个 ReferenceError 。
关于 let 的是否存在变量提升,我们何以用下面的例子来验证:
let 变量如果不存在变量提升, console.log(name) 就会输出 ConardLi ,结果却抛出了 ReferenceError ,那么这很好的说明了, let 也存在变量提升,但是它存在一个“暂时死区”,在变量未初始化或赋值前不允许访问。
变量的赋值可以分为三个阶段:
关于 let 、 var 和 function :
依次输出:undefined -》 10 -》 20
答案: D
colorChange 方法是静态的。静态方法仅在创建它们的构造函数中存在,并且不能传递给任何子级。由于 freddie 是一个子级对象,函数不会传递,所以在 freddie 实例上不存在 freddie 方法:抛出 TypeError 。
1.使用第一次push,obj对象的push方法设置 obj 获取为 undefined
undefined {n:2}
首先,a和b同时引用了{n:2}对象,接着执行到a.x = a = {n:2}语句,尽管赋值是从右到左的没错,但是.的优先级比=要高,所以这里首先执行a.x,相当于为a(或者b)所指向的{n:1}对象新增了一个属性x,即此时对象将变为{n:1;x:undefined}。之后按正常情况,从右到左进行赋值,此时执行a ={n:2}的时候,a的引用改变,指向了新对象{n:2},而b依然指向的是旧对象。之后执行a.x = {n:2}的时候,并不会重新解析一遍a,而是沿用最初解析a.x时候的a,也即旧对象,故此时旧对象的x的值为{n:2},旧对象为 {n:1;x:{n:2}},它被b引用着。后面输出a.x的时候,又要解析a了,此时的a是指向新对象的a,而这个新对象是没有x属性的,故访问时输出undefined;而访问b.x的时候,将输出旧对象的x的值,即{n:2}。
在比较相等性,原始类型通过它们的值进行比较,而对象通过它们的引用进行比较。 JavaScript 检查对象是否具有对内存中相同位置的引用。
我们作为参数传递的对象和我们用于检查相等性的对象在内存中位于不同位置,所以它们的引用是不同的。
这就是为什么 { age: 18 } === { age: 18 } 和 { age: 18 } == { age: 18 } 返回 false 的原因。
所有对象键(不包括 Symbols )都会被存储为字符串,即使你没有给定字符串类型的键。这就是为什么 obj.hasOwnProperty(’1’) 也返回 true 。
上面的说法不适用于 Set 。在我们的 Set 中没有 “1” : set.has(’1’) 返回 false 。它有数字类型 1 , set.has(1) 返回 true 。
这题考察的是对象的键名的转换。
catch 块接收参数 x 。当我们传递参数时,这与变量的 x 不同。这个变量 x 是属于 catch 作用域的。
之后,我们将这个块级作用域的变量设置为 1 ,并设置变量 y 的值。现在,我们打印块级作用域的变量 x ,它等于 1 。
在 catch 块之外, x 仍然是 undefined ,而 y 是 2 。当我们想在 catch 块之外的 console.log(x) 时,它返回 undefined ,而 y 返回 2 。

本文相关文章:
javascript 菜鸟教程(自学web前端,应该从哪些知识入门呢)
2026年5月15日 14:38
更多文章:
创建网页的标准通用标记语言(给不懂电脑的人解释一下“网页标记语言”)
2026年5月15日 14:55
个人网站设计首页界面(网页设计如何设为首页网页设计如何设为首页页面)
2026年4月29日 03:04
叉车证查询系统网址?如何仿制网站(一模一样),制造后台管理系统CMS
2026年5月6日 05:54
python简单小游戏代码(用Python写一个简单的小游戏)
2026年4月23日 14:35



















