前端面试

186 阅读21分钟

1 v-if / v-for 同时使用

  自:for 优先级要比if高 ,如果一起用会造成性能浪费,可以for 写if里面,或者用computed

2 性能优化

    精灵图合并,减少HTTP请求;压缩HTML、CSS、JavaScript文件;使用CDN托管静态文件;少用行业样式;减少dom操作;图片预加载、懒加载;开启服务器端的Gzip压缩(对文本资源非常有效);延长资源缓存时间;

3 web安全

 css攻击(跨域脚本攻击) 防御:输入内容的限制校验;编码-转意敏感字符 ;过滤-onclick等事件、style、script节点、iframe节点;httponle-防止劫取 Cookie;

csrf攻击:(跨站请求伪造)防御:token 双重cookie;

 sql注入(让服务器执行攻击者的SQL语句) 防御:输入校验、数据库权限分配;

答案: blog.csdn.net/Ed7zgeE9X/a…

             www.jianshu.com/p/544bb4bcc…

4 缓冲

   DNS缓冲

   进去页面先DNS查询,找到域名对应的服务器的IP地址,再发送请求

DNS域名查找先在客户端进行递归查询

**
**

在任何一步找到就会结束查找流程,而整个过程客户端只发出一次查询请求

如果都没有找到,就会走DNS服务器设置的转发器,如果没设置转发模式,则向13根发起解析请求,这里就是迭代查询,如图

13根:
全球共有13个根域服务器IP地址,不是13台服务器!
因为借助任播技术,可以在全球设立这些IP的镜像站点,所以访问的不是唯一的那台主机

浏览器缓冲

浏览器与服务器通信的方式为应答模式,即是:浏览器发起HTTP请求 – 服务器响应该请求。那么浏览器第一次向服务器发起该请求后拿到请求结果,会根据响应报文中HTTP头的缓存标识,决定是否缓存结果,是则将请求结果和缓存标识存入浏览器缓存中,简单的过程如下图:

1625202449441.jpg

强缓冲

 第一次请求-  响应头返回过期时间,没有过期直接使用,不需要向服务器发请求。

缺点:过期之后不管资源是否变换都需要重新请求

-Expires-  :

expires: Wed, 22 Nov 2021 08:41:00 GMT

-Cache-Control-  : (优先级高于expires)

cache-control:max-age=300

协商缓冲

1.  响应头返回资源最后修改时间

     -last-modified(第一次请求)  VS    If-Modified-Since(再次请求) 相同返回304,不同返回200和新资源

缺点:即使打开也算修改

2  响应头返回资源文件的唯一标识,精确感知文件内容不同

   -  Etag    vs     If-None-Match     相同返回304,不同返回200和新资源

  Last-Modigied 和Etag 区别

   1.Etag 感知精准度高于last-modified

   2.last-modified 性能高于Etag,因为Etag是由服务器生成的,影响性能,不能替代只是补充加强。

5 querySelector 和 getElementBy

区别:querySelector 属于W3C 中 Selectors API 规范;返回的是文档节点集合;静态集合

            getElementBy 属于W3C 中 DOM 规范 ;返回HTML元素集合;动态集合;

6 DocumentFragment 文档碎片节点

没有父级的最小文档对象,轻量版的document。documentfragment节点不属于DOM树,变化不会起dom树变化,所以不会引起回流重绘。

使用:将documentFragment作为暂时的节点储存器,将存储的节点一次性加入DOM树,减少回流。

vue使用:双向绑定v-for/model——每个vue实例都有一个根元素Id属性是el,找到要渲染的部分,使用createDocumentgrament()创建一个documentgrament,遍历根元素的所有子元素,劫持插入documentgrament,执行vue编译,这个编译就是v-model等,然后再吧编译完成的documentgrament返回给dom根元素。

7 js数据类型,原始数据类型和引用数据类型的区别?

   js数据类型:number,boolean,string,null,underfined,object,symbol,bigint

   bigint(BigInt 用于当整数值大于Number数据类型支持的范围。number最大安全整数 2^53 - 1)

栈:原始数据类型(string boolean number undefined null)

堆:引用数据类型(function,array , object)

区别是_存储位置不同_:

 基本数据类型在栈中的简单数据段,占据空间小,大小固定,属于频发使用数据;

引用数据类型在堆中的对象,占据空间大,大小不固定,在栈中存储了指针,指向堆的地址。

8 event loop  循环机制

js是单线程,所有同步任务在主线程执行,形成执行栈;主线程之外还有“任务队列”,执行栈执行结束后会读取“任务队列“,异步任务结束等待状态进去执行栈开始执行。

执行栈执行完同步任务后,执行栈也为空就会去执行微任务,微任务执行后执行宏任务。

9 什么是闭包,闭包的应用有哪些地方,闭包优缺点

定义:有权访问另一个函数内变量的函数

闭包基本上就是⼀个函数内部返回⼀个函数

应用:防抖,柯里化

优点:

  • 可以读取函数内部的变量
  • 将变量始终保持在内存中
  • 可以封装对象的私有属性和私有方法

缺点:比较耗内存,造成内存溢出

const add2 = function (){
   var count
   return function add (){ // 访问了外部变量的函数
      count += 1
   }
}()

10 map / weakmap 

Map本质上是一个键值对的集合。和传统对象结构相比,传统的对象只能用string为键名, map的键key 为任意类型。

区别:1 map的key是任意类型,weakmap 只能是对象(除了null)

2 map 是强引用;weakmap 是弱引用(可被垃圾回收)

3 map 可遍历;weakmap 不可遍历

// 1. 通过new Map来创建dataMap容器
const dataMap = new Map();
// 2. 获取节点对象,作为测试数据
const element = document.querySelector(".node");
// 3. 通过 set 方法给 dataMap 中指定键和对应的值
dataMap.set(element,'objectData');
// 4. 通过 get 来从 dataMap 中获取键名对应的值
console.log(dataMap.get(element));
// 5. 揭开面目
console.log(dataMap);  

--------map 属性方法 set map has delete clear
// 判断传入的键是否在当前的map对象中 返回boolean
cosole.log(dataMap.has('name'))
//删除传入的键
dataMap.delete('name')
//清除所有成员
dataMap.clear()

参考:juejin.cn/post/699310…

11 webworker (运行在后台的js)

webworker 是运行在后台的 JavaScript,不会影响页面的性能。

Web Worker 是 HTML5 标准的一部分,这一规范定义了一套 API,它允许一段 JavaScript 程序运行在主线程之外的另外一个线程中。webworker给浏览器带来了后台计算的能力,把耗时的任务分配给worker线程来做,在很大程度上缓解了主线程UI渲染阻塞的问题,提升页面性能

self 代表worker 进程自己,而不是window,

创建 worker : const worker = new Worker('https://~.js')

主线程与 worker 线程通信:    worker.postMessage({ hello: ['hello', 'world'] });

主线程关闭worker线程 :worker.terminate(); 

参考: juejin.cn/post/684490…

12 http 和 https

http:是客户端和服务端请求和应答的标准(tcp),是超文本传输协议。

  https: 以安全为目标的http通道,http加入SSL层加密。

 优缺点:

  • http 是超文本传输协议,信息是明文传输,HTTPS 协议要比 http 协议安全,https 是具有安全性的 ssl 加密传输协议,可防止数据在传输过程中被窃取、改变,确保数据的完整性(当然这种安全性并非绝对的,对于更深入的 Web 安全问题,此处暂且不表)。

  • http 协议的默认端口为 80,https 的默认端口为 443。

  • http 的连接很简单,是无状态的。https 握手阶段比较费时,会使页面加载时间延长 50%,增加 10%~20%的耗电。

  • https 缓存不如 http 高效,会增加数据开销。

  • Https 协议需要 ca 证书,费用较高,功能越强大的证书费用越高。

  • SSL 证书需要绑定 IP,不能再同一个 IP 上绑定多个域名,IPV4 资源支持不了这种消耗。

13 HTTP/1 .1和 HTTP/2区别

  • 新的二进制格式(Binary Format),HTTP1.x解析是基于文本的,基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。

  • 多路复用(MultiPlexing),即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。

  • header压缩,HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。

  • 服务端推送(server push),同SPDY一样,HTTP2.0也具有server push功能。

14 TCP 3次握手、4次挥手

 TCP 3次握手 

  1. 建立连接,客户端向服务端发包
  2. 服务端收到包,向客户端发送自己的包
  3. 客户端向服务端发送确认包

TCP 4次挥手

  1. 客户端向服务端发送连接释放请求

  2. 服务端发送确认并同意关闭请求

  3. 服务端发送请求关闭连接

  4. 客户端确认包

15 TCP  UDP 

  • TCP是面向链接的,而UDP是面向无连接的。
  • TCP仅支持单播传输,UDP 提供了单播,多播,广播的功能。
  • TCP的三次握手保证了连接的可靠性; UDP是无连接的、不可靠的一种数据传输协议,首先不可靠性体现在无连接上,通信都不需要建立连接,对接收到的数据也不发送确认信号,发送端不知道数据是否会正确接收。
  • UDP的头部开销比TCP的更小,数据传输速率更高实时性更好

TCP 和 UDP 应用场景

UDP的应用场景:即时通信。面向数据报方式;网络数据大多为短消息;拥有大量客户端;对数据安全性无特殊要求;网络负担重但对响应速度要求高的场景。eg: IP电话、实时视频会议等。

TCP的应用场景:对数据准确性要求高,速度可以相对较慢的。eg: 文件传输、邮件的发送与接收等。

16  HTTP 请求跨域

同源策略:只要协议、域名、端口有任何一个不同,都被当作是不同的域。

解决方案:

  • JSONP 利用

  • CORS(Cross-origin resource sharing)跨域资源共享 服务器设置对CORS的支持原理:服务器设置Access-Control-Allow-Origin HTTP响应头之后,浏览器将会允许跨域请求

  • proxy代理 目前常用方式,通过服务器设置代理

  • window.postMessage() 利用h5新特性它更多地用于窗口间的消息传递****。

  • Node 中间件和 Nginx 反向代理都是利用了服务器对服务器没有同源策略限制

  • Websocket (全双工通信协议)也是一种跨域的解决方案

  • document.domain, window.name, location.hash 逐渐淡出历史舞台,作为替代 PostMessage 是一种不错的方案

参考:juejin.cn/post/684490…

17  postMessage

postMessage :是html5引入的API,postMessage()方法允许来自不同源的脚本采用异步方式进行有效的通信,可以实现跨文本文档,多窗口,跨域消息传递.多用于窗口间数据通信,这也使它成为跨域通信的一种有效的解决方案.

使用场景:

  • 跨域通信(多用于窗口消息传递)
  • webworker(运行在后台的js线程,用于和主线程通信-(上述11小点))
  • Service worker 离线缓冲 用于与页面通信

参考:juejin.cn/post/684490…

18  预检请求

预检请求(preflight request),是一个跨域请求,用来校验当前跨域请求能否被理解。

**针对CORS请求,浏览器将请求分成两个类型:**简单请求和非简单请求(预检请求)

简单请求:请求头有Origin字段,表示请求来自哪一个源;响应头有Access-Control-Allow-Origin字段,它的值要么包含由 Origin 首部字段所指明的域名,要么是一个 "*",表示接受任意域名的请求。

使用以下方法之一:GET, HEAD, POST,

并且 Content-Type 的值仅限于下列三者之一:

  • text/plain
  • multipart/form-data
  • application/x-www-form-urlencoded

非简单请求:正式通信前发送预检请求,目的在于询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些 HTTP 动词和头信息字段,只有得到肯定答复,浏览器才会发出正式的请求,否则就报错。

  参考:juejin.cn/post/684490…

19从输入URL到页面加载的全过程

  • DNS解析
  • 发起TCP连接
  • 发送HTTP请求
  • 服务器处理请求并返回HTTP报文
  • 浏览器解析渲染页面
  • 连接结束。

参考:juejin.cn/post/684490…

20 hash history

    aaa.com#a/index   hash 模式

    aaa.com/a/index     history模式

21 computed 和 watch 区别

   computed计算属性:依赖其他属性值,并且computed 的值有缓冲,只有依赖的值发生改变,下一次获取才会重新计算。(依赖属性不改变可以直接缓冲获取computed,不需要重新计算)

watch 监听属性:更多的是观察作用,无缓冲性

多个因素影响一个显示用computed;  一个因素影响多个因素显示用watch

22 普通函数和箭头函数

   最大的区别在于this的指向问题(严格来说,其实箭头函数没有自己的this

  • 箭头函数不能用new来创建构造函数;普通函数可以

  • 不可以使用argumengts对象,不存在;

  • 普通函数的this是动态的, 箭头函数的this是包裹箭头函数的那个对象

  • 箭头函数不能通过bind,call,apply来改变this,但是可以用这几个方法,只是this的值不受这几个方法控制。

23 let const 区别

  • let 命令不存在变量提升
  • 存在const let 会形成封闭作用域
  • 不允许重复声明
  • const 声明的是常量,不能修改,但是如果定义的是对象,是可以修改对象内部的数据。

24 js是单线程的,但是为什么要设计成单线程?   

    这主要和js的用途有关,js是作为浏览器的脚本语言,主要是实现用户与浏览器的交互,以及操作dom;这决定了它只能是单线程,否则会带来很复杂的同步问题。 

 单线程:在同一时间只能做一件事
js也有多线程能力,即web worker,但有限制,无法操作DOM
因为js主要功能是操作DOM,如果有多线程,其中一个线程要删除一个div,另外一个线程要给这个div添加子元素,那到底要听那个线程的呢,这样会产生很多冲突.

 为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。

25 JS单线程的问题及解决方法

单线程引发的问题:所有任务都需要排队,前一个任务结束,才会执行后一个任务,这样一些耗时很长的任务就会阻塞页面的操作,如果一值等待则会非常不合理
解决办法:引入异步,添加了一个消息队列, 即将一些需要等待的任务分类按顺序放在消息队列中,先执行可以直接执行的任务,之后不停的去消息队列询问是否有任务可以执行,有就将任务重新放到主线程里执行,没有就继续之前的操作,这个过程就是js的事件轮询
1.所有任务都在主线程上执行,形成一个执行栈
2.如果执行栈中的所有同步任务执行完毕,js就会读取消息队列中的异步任务,如果有可以执行的任务就把它放到执行栈中并开始执行
3.主线程不断重复上面的第二步,这样的一个循环称为事件循环

26 原型 原型链

  • 所有的函数都有prototype属性(原型)
  • 所有的对象都有__proto__属性
  • Javascript中,每个函数都有⼀个原型属性prototype指向⾃⾝的原型,⽽由这个函数创建的对象也有⼀个proto属性指向这个 原型,⽽函数的原型是⼀个对象,所以这个对象也会有⼀个proto指向⾃⼰的原型,这样逐层深⼊直到Object对象的原型,这样就 形成了原型链

cat.proto === Animal.prototype cat.constructor==Animal

27  vue组件中data为什么必须是⼀个函数?

因为javaScript的特性所导致,在component中,data必须以函数的形式存在,不可以是对象。 组件中的data写成⼀个函数,数据以函数返回值的形式定义,这样每次复⽤组件的时候,都会返回⼀份新的data,相当于每个组件 实例都有⾃⼰私有的数据空间,他们只负责各⾃维护数据,不会造成混乱。⽽单纯的写成对象形式,就是所有组件实例共⽤了⼀个 data,这样改⼀个全部都会修改。

28  常见状态码

  • 1xx: 接受,继续处理

  • 200: 成功,并返回数据

  • 201: 已创建

  • 202: 已接受

  • 203: 成为,但未授权

  • 204: 成功,无内容

  • 205: 成功,重置内容

  • 206: 成功,部分内容

  • 301: 永久移动,重定向

  • 302: 临时移动,可使用原有URI

  • 304: 资源未修改,可使用缓存

  • 305: 需代理访问

  • 400: 请求语法错误

  • 401: 要求身份认证

  • 403: 拒绝请求

  • 404: 资源不存在

  • 500: 服务器错误

29 做过的vue性能优化

  • 对象层级不要过深,否则性能就会差。

  • 不需要响应式的数据不要放在 data 中(可以使⽤ Object.freeze() 冻结数据)

  •  v-if 和 v-show 区分使⽤场景 

  • computed 和 watch 区分场景使⽤

  •  v-for 遍历必须加 key,key最好是id值,且避免同时使⽤ v-if 

  • ⼤数据列表和表格性能优化 - 虚拟列表 / 虚拟表格 

  • 防⽌内部泄露,组件销毁后把全局变量和时间销毁

  •  图⽚懒加载 

  • 路由懒加载 

  • 异步路由 

  • 第三⽅插件的按需加载

  •  适当采⽤ keep-alive 缓存组件 

  • 防抖、节流的运⽤

  •  服务端渲染 SSR or 预渲染

30 Vue.js 双向绑定的原理

Vue.js 2.0 采用数据劫持(Proxy 模式)结合发布者-订阅者模式(PubSub 模式)的方式,通过 Object.defineProperty()来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

每个组件实例都有相应的watcher程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知watcher重新计算,从而致使它关联的组件得以更新。

Vue.js 3.0, 放弃了Object.defineProperty ,使用更快的ES6原生 Proxy (访问对象拦截器, 也称代理器)

31 vue 中使用了哪些设计模式?

  • 1、工厂模式 - 传入参数即可创建实例

  • 虚拟 DOM 根据参数的不同返回基础标签的 Vnode 和组件 Vnode。

  • 2、单例模式 - 整个程序有且仅有一个实例

  • vuex 和 vue-router 的插件注册方法 install 判断如果系统存在实例就直接返回掉。

  • 3、发布-订阅模式。(vue 事件机制)

  • 4、观察者模式。(响应式数据原理)

  • 5、装饰器模式(@装饰器的用法)

  • 6、策略模式,策略模式指对象有某个行为,但是在不同的场景中,该行为有不同的实现方案 - 比如选项的合并策略。

32 Vuex 页⾯刷新数据丢失怎么解决? 

  • 需要做 vuex 数据持久化,⼀般使⽤本地储存的⽅案来保存数据,可以⾃⼰设计存储⽅案,也可以使⽤第三⽅插件。

  •  推荐使⽤ vuex-persist (脯⾁赛斯特)插件,它是为 Vuex 持久化储存⽽⽣的⼀个插件。不需要你⼿动存取 storage,⽽是直接将 状态保存⾄ cookie 或者 localStorage中。

Cookie、sessionStorage、localStorage 的区别

相同点

  • 存储在客户端

不同点

  • cookie数据大小不能超过4k;sessionStorage和localStorage的存储比cookie大得多,可以达到5M+

  • cookie设置的过期时间之前一直有效;localStorage永久存储,浏览器关闭后数据不丢失除非主动删除数据;sessionStorage数据在当前浏览器窗口关闭后自动删除

  • cookie的数据会自动的传递到服务器;sessionStorage和localStorage数据保存在本地

浏览器重绘与重排的区别?

  • 重排/回流(Reflow):当DOM的变化影响了元素的几何信息,浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置,这个过程叫做重排。表现为重新生成布局,重新排列元素。
  • 重绘(Repaint): 当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘。表现为某些元素的外观被改变

『重绘』不一定会出现『重排』,『重排』必然会出现『重绘』。

HTML&CSS

BFC(块级格式上下文)

BFC的概念

字体颜色为红色,字体为22号<\font>

BFCBlock Formatting Context 的缩写,即块级格式化上下文。BFC是CSS布局的一个概念,是一个独立的渲染区域,规定了内部box如何布局, 并且这个区域的子元素不会影响到外面的元素,其中比较重要的布局规则有内部 box 垂直放置,计算 BFC 的高度的时候,浮动元素也参与计算。

BFC的原理布局规则

  • 内部的Box会在垂直方向,一个接一个地放置
  • Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
  • 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反
  • BFC的区域不会与float box重叠
  • BFC是一个独立容器,容器里面的子元素不会影响到外面的元素
  • 计算BFC的高度时,浮动元素也参与计算高度
  • 元素的类型和display属性,决定了这个Box的类型。不同类型的Box会参与不同的Formatting Context

如何创建BFC?

  • 根元素,即HTML元素
  • float的值不为none
  • position为absolute或fixed
  • display的值为inline-block、table-cell、table-caption
  • overflow的值不为visible

BFC的使用场景

  • 去除边距重叠现象

  • 清除浮动(让父元素的高度包含子浮动元素)

  • 避免某元素被浮动元素覆盖

  • 避免多列布局由于宽度计算四舍五入而自动换行

作者:Gaby
链接:juejin.cn/post/701659…
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

webpack

bable

AST语法树

tree shacking

原理esm,tree shaking 就是通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。它依赖于 ES2015 模块语法的 静态结构 特性,例如 import 和 export。

0.1+0.2!==0.3

console.log(parseFloat((0.1 + 0.2).toFixed(10)) === 0.3); // true