前端面试题汇总(2)

本文汇总了前端面试中常见的100道JavaScript核心知识点,包括处理异步的方法(回调、Promise、async/await)、JS弹出框、URL编码解码、日期转换、BOM与DOM、数据类型转换、懒加载、setTimeout与setInterval的区别、闭包、原型链、HTTP状态码、事件冒泡等。通过深入理解这些知识点,能够帮助开发者更好地应对前端面试和日常开发。

51、处理异步的方法有哪些

(1)回调函数

function timeoutCallback(() {
   console.log('start')
   setTimeout(() => {
      console.log('callback')
   },1000)
   console.log('done')
})
timeoutCallback()

(2)Promise

function matexiaPromise() {
  return new Promise(resolve => {
    console.log('promise')
    resolve()
  })
}
matexiaPromise()
  .then(() => console.log('then 1'))
  .then(() => setTimeout(() => console.log('setTimeout'), 0))
  .then(() => console.log('then 2'))
  .catch((err) => console.log('catch:', err))

        Promise是通过微任务队列来驱动它的;微任务队列的触发时机是在被栈清空时,JavaScript引擎会先确认微任务队列没有东西,有的话就优先执行,直到清空后才从队列拿出新任务到栈上。

(3)async/await

function matexiawait(time) {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('wait:', time)
      resolve(time)
    }, time)
  })
}
await matexiawait(1000, () => console.log('bar'))
console.log('foo')

         通过把setTimeout包装成Promise,再用await关键字调用,可以看到结果会是同步执行的先出现bar,再出现foo,也就是将异步事件写成同步处理。

52、JS种有哪些不同类型的弹出框

  •  alert('提示信息')
  •  confirm("确认信息")
  •  prompt("弹出输入框")

53、如何在JS中编码和解码URL

  • 编码:encodeURl()
  • 解码:decodeURl()

54、如何将JS日期转换为ISO标准

var date = new Date();
var n = date.toISOString();

console.log(n);  //YYYY-MM-DDTHH:mm:ss.sssZ

55、什么是BOM?有哪些api?

         BOM是Browser Object Model,浏览器对象模型,BOM提供了专门操作浏览器窗口或软件的API。BOM核心是window,而window对象又具有双重角色,它既是通过js访问浏览器窗口的一个接口,又是Global(全局)对象。常用api如下:

  • window.history:浏览器访问历史信息
  • window.location:浏览器当前URL信息
  • window.navigator:浏览器本身信息
  • window.screen:客户端屏幕信息,可获取用户设备的种类
  • setTimeout
  • alert等等

56、JS种的substr()和substring()有什么区别

  • ubstring(startIndex,endlndex):它返回从startIndex的子字符串(不包含endIndex)
  • substr(startIndex,length):它从startIndex返回子字符串并返回‘length’个字符数

57、JS有哪些内置对象

  • 数据封装类对象:Object、Array、Boolean、Number、String
  • 其它对象:Function、Arguments、Math、Date、RegExp、Error
  • ES6新增对象:Symbol、Map、Set、Promises、Proxy、Reflect

58、如何实现懒加载

  • 根据用户的浏览需要加载的内容:即用户浏览完面前页面内容,判断用户是否即将到达浏览器底部,再加载内容。
  • 如需加载大量内容,可使用fragment来优化
  • 大部分加载是使用滑动和滚轮来触发,会造成不断触发,可使用函数节流做优化,防止用户不断触发

59、setTimeout和setInterval的区别,包含内存方面的分析

  • setTimeout:间隔一段时间之后执行一次调用
  • setInterval:每隔一段时间循环调用,直至clearInterval结束

内存方面

  • setTimeout只需要进入一次队列,不会造成内存溢出
  • setInterval因为不计算代码执行时间,有可能同时执行

60、解释一下”use strict“?

严格模式”use strict“是ES5种引入的新指令

  • 使用”use strict“指令的目的是强制执行严格模式下的代码
  • 在严格模式下,不可在未声明变量的情况下使用变量
  • 早期版本的js忽略了”use strict“

61、引起内存泄漏的操作有哪些

  • 全局变量引起
  • 闭包引起
  • dom清空,事件未清除
  • 子元素存在引用
  • 未清除的计时器

62、短路运算

  • let a = 123 || 456 : 123为真,终止右侧运算,直接返回:a = 123
  • 短路:如左侧为真,则不再进行右侧运算,同时返回左侧表达式运算结果
  • 如果左侧为假,则执行右侧表达式运算,并返回右侧计算结果

63、从浏览器地址栏输入url到显示页面的步骤

  • 根据请求的url交给DNS域名解析,查找真实的IP,再向服务器发起请求
  • 服务器交给后台处理完成后返回数据,浏览器接收返回的数据
  • 浏览器收到数据后,对加载资源进行解析,建立相应的内部数据结构
  • 载入解析到的资源文件,渲染到页面

64、递归

  • 递归:指在当前方法内调用自己的这种现象
  • 递归的分类:
    • 递归分为两种:直接递归和简介递归
    • 直接递归称为方法自身调用自己
    • 间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法
  • 注意事项:
    • 递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出
    • 在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出
    • 构造方法,禁止递归
  • 递归的使用前提
    • 当调用方法的时候,方法的主体不变,每次调用方法的参数不同,可以使用递归
  • 递归场景:深拷贝、遍历DOM树

65、new关键字创建流程

  1. 在内存中创建一个新的空对象
  2. 让this指向这个新的对象
  3. 执行构造函数里面的代码,给这个新对象添加属性和方法(给对象赋值)
  4. 返回这个新对象(所以构造函数里面不需要return)

66、构造函数 原型对象 实例对象三者的关系

  1. 创建构造函数时,系统自动分配一个原型对象,构造函数种的prototype属性,指向这个原型对象
  2. 原型对象中的constructor属性,指向它的构造函数
  3. new一下,创建实例对象,他的_proto_属性,指向原型对象,从而可以访问到原型上的成员

67、原型和原型链是什么

       当实例对象,在自身找不到方法时,会向上一级原型对象上查找,如果找不到,又会到原型对象上一级的原型对象上查找,这种链式查找机制,就叫原型链

68、原型链的终点是什么

        null

69、JS语言是通过什么技术实现面向对象继承的

        原型链

70、instanceof运算符

  • 语法:对象instanceof构造函数
  • 作用:检测构造函数的原型prototype在不在这个对象的原型链上

71、call、apply、bind的区别

  • 相同点:都可以修改函数的this指向
  • 不同点:
    • 传参方式不同,call用于单个参数,apply参数必须是数组
    • call和apply,修改函数的this指向,并立即调用函数
    • bind,也可以修改函数的this指向,但不调用函数

72、http和https的区别

  • https的端口是443,而http的端口是80,且两者使用的是完全不同的连接方式
  • https协议需要到CA申请证书,申请证书可能会需要一定的费用,http则不需要
  • https是由SSL/TLS加密传输协议构建的可进行加密传输、身份认证的网络协议,安全性更高
  • http是超文本传输协议,信息是明文传输,http的连接很简单,是无状态的

73、get和post的区别

  • get
    • get是从服务器上获取数据
    • 在url后面拼接参数,传递数据量小,约4k
    • 传递的数据会在地址栏显示,速度快,安全性低
    • 会缓存数据,参数会保留在浏览器的历史记录里
  • post
    • post是向服务器传送数据
    • post传输的数据量较大,一般默认为不受限制
    • 请求不会被缓存,也不会保留在浏览器历史记录里,安全性比较高

74、Jsonp作用及原理

  • jsonp不属于AJAX请求,他们之间没有任何关系,jsonp只可发起GET请求
  • jsonp的作用:利用浏览器同源策略,解决跨域问题

jsonp原理:

  • 利用script标签可跨特性,发起jsonp请求,并提供一个callback函数来接收数据
  • jsonp发起请求之后后台包装好一段json,并把数据放在一个callback函数返回一个js文件夹回来
  • 动态引入这个文件,下载完成之后,会去调用callback函数,callback函数接收一个参数()

简单理解:

  • 通过script的src属性发送get请求,服务器接收请求,以函数调用的形式将数据携带回来

扩展:

  • 第三方产生的响应为json数据的包装(故称之为jsonp,即json padding)
  • 形如:callback({"name":"andy","age":"33"})
function success(data){
   console.log(data)   //接收JSONP响应回来的数据data
}

<script src="http://wwwwww?callback=success"></script>  //发起jsonp请求

75、浏览器同源策略

  • URL由3部分组成:协议、域名(指向主机)、端口号。只有这三个都相同时才成为同源。
  • 同源策略是浏览器的一种安全策略:A域名的js不能直接访问B域名的信息。

76、如何解决跨域问题

   方式一:跨域资源共享(cors)

  • 浏览器将CORS请求分成两类:简单请求和预检请求
  • 解决方式就是服务器在响应头中加入字段:Access-contro-allowl-origion:Origion,那么该Origion就可以访问了。

   方式二:通过jsonp实现

  • 通常为了减轻web服务器的负载,我们把js、css、img等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许,基于此原理,我们可以通过动态创建script,再请求一个带参网址实现跨域通信

   方式三:vue中设置代理服务器

  • 跨域问题只存在浏览器,如果是服务器和服务器之间的通信是不存在跨域问题的
  • 可以在vue-cli中设置代理服务器实现跨域请求

77、什么是webSocket

  •  webSocket是HTML5的一种新协议
  • 实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通信
  • 它建立在TCP之上,同HTTP一样通过TCP来传输数据

    和HTTP最大的不同是

  • webSocket是双向通信协议,建立连接后,webSocket服务器和Browser/Client Agent都能主动向对方发送或接收数据,就像Socket一样
  • webSocket需要类似TCP的客户端和服务端通过握手连接成功后才能相互通信

78、在地址栏输入URL到数据返回的过程

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

79、怎么理解TCP三次握手

  • 第一次握手:建立连接时,客户端发送SYN包到服务器,等待服务器确认
  • 第二次握手:服务器收到SYN包,必须确认顾客的SYN,同时自己也发送一个SYN包(syn=n)到客户端
  • 第三次握手:客户端收到服务器的SYN+ACK,向服务器发送确认包ACK,发送完毕,客户端和服务器进入(TCP连接成功)状态,完成三次握手

80、原生ajax请求步骤

  • 创建xhr异步实例对象:const xhr = new HTMLHttpRequest()
  • 设置请求行:xhr.open()
  • 设置请求头:xhr.setRequestHeader(...)===>只有POST请求需要设置,GET请求跳过这一步
  • 设置请求体:xhr.send() ===>POST参数写在这里,GET没有请求体,不写或者写null
  • 监听异步对象状态的变化:xhr.onreadystatechange(){...}

81、BOM 和 DOM 的关系

  • BOM全称Browser Object Model,即浏览器对象模型,主要处理浏览器窗口和框架。
  • DOM全程Document Object Model,即文档对象模型,是HTML和XML的应用程序接口(API),遵循W3C标准,所有浏览器公共遵守的标准
    • JS是通过访问BOM(Browser Object Model)对象来访问、控制、修改客户端(浏览器)
    • 由于BOM的window包含了document,window对象的属性和方法是直接可以使用而且被感知的
    • 因此可以直接使用window对象的document属性,通过document属性就可以访问、检索、修改XHTML文档文档内容与结构
    • 因为document对象又是DOM的根节点

       可以说,BOM包含了DOM(对象),浏览器提供出来给与访问的是BOM对象,从BOM对象再访问DOM对象,从而js可以操作浏览器以及浏览器读取到的文档。

82、你对浏览器内核的理解

主要分成两部分:渲染引擎JS引擎

最开始渲染引擎和JS引擎并没有区分的很明确,后来JS引擎越来越独立,内核就倾向与只指渲染引擎

  • 渲染引擎:
    • 负责取得页面的内容(HTML、XML、图像等等)、整理信息(例如加入CSS等),以及计算网页显示方式,然后会输出至显示器或打印机
    • 浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不同。所有网页浏览器、电子邮件客户端以及其他需要编辑、显示网络内容的应用程序都需要内核。
  • JS引擎则
    • 解析和执行javascript来实现网页的动态效果

83、讲一讲JavaScript的装箱和拆箱

  • 装箱:把基本数据类型转化为对应的引用数据类型的操作
  • 拆箱:将引用数据类型转化为对应的基本数据类型的操作

代码验证,str是基本数据类型,怎么调用indexOf的呢

const str = 'hello world!'
const index = str.indexOf('!')
console.log(index)  //11
  • 原来是JavaScript内部进行了装箱操作
    • 创建String类型的一个实例
    • 在实例上调用指定的方法
    • 销毁这个实例
var str = new String('hello world!')
const index = str.indexOf('!')
str = null
console.log(index)   //8
  • 通过valueOf或者toString方法实现拆箱操作
var num = new Number(12345);
var str = new String("hello world!");

console.log(typeof num);   // object
console.log(typeof str);   // object
console.log(typeof num.valueof());   // number
console.log(typeof str.valueOf());   // string

console.log(typeof num.toString());   // string
console.log(typeof str.toString());   // string

84、如何实现浏览器内多个标签页之间的通信

        实现多个标签页之间的通信,本质上都是通过中介者模式来实现的。因为标签页之间没有办法直接通信,因此我们可以找一个中介者来让标签页和中介者进行通信,然后让这个中介者进行消息的转发。

  1. 使用Websocket,通信的标签页连接同一个服务器,发送消息到服务器后,服务器推送消息给多有连接的客户端
  2. 可以调用localStorage,localStorage在另一个浏览上下文里被添加、修改或删除时,它都会触发一个storage事件,我们可以通过监听storage事件,控制它的值来进行页面信息通信
  3. 如果我们能够获得对应标签页的引用,通过postMessage方法也是可以实现多个标签页通信的

85、简述伪类和伪元素

伪类:

       伪类用于当已有元素处于某种状态时,为其添加对应的样式,这个状态是根据用户行为变化而变化的。比如说:hover。它只有处于dom树无法描述的状态才能为元素添加样式,所以称为伪类。

伪元素:

       伪元素用于创建一些原本不在文档树中的元素,并为其添加样式,比如说::before。虽然用户可以看到这些内容,但是其实他不在文档树种。

区别:

       伪类的操作对象是文档

86、Vue的父组件和子组件生命周期钩子执行顺序是什么

  1. 加载渲染过程:父 beforeCreate -> 父 created -> beforeMount ->子 beforeCreate ->子 created ->子 beforeMount -> mounted ->父 mounted
  2. 子组件更新过程:父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
  3. 父组件更新过程:父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
  4. 销毁过程:父 beforeDestroy -> 子 beforeDestroy ->子 destroyed -> 父 destroyed

87、Vue中 computed 和 watch 的差异

  1. computed 是计算一个新的属性,并将该属性挂在到Vue实例上,而watch是监听已经存在且已挂载到Vue实例上的数据,所以用watch同样可以监听computed 计算属性的变化
  2. computed 本质是一个惰性求值的观察者,具有缓存性,只有当依赖变化后,第一次访问computed 值,才会计算新的值。而watch则是当数据发送变化便会调用执行函数
  3. 从使用场景上来说,computed适用一个数据被多个数据影响,而watch使用一个数据影响多个数据

88、webpack 中 loader 和 plugin 的区别是什么

loader:loader是一个转换器,将A文件进行编译成B文件,属于单纯的文件转换过程;

plugin:plugin是一个扩展器,它丰富了webpack本身,针对是loader结束后,webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听webpack打包过程中的某些节点,执行广泛的任务。

89、Node中的内存泄露问题和解决方案

内存泄漏的原因

  1. 全局变量:全局变量挂在 root 对象上,不会被清除掉
  2. 闭包:如果闭包未释放,就会导致内存泄漏
  3. 事件监听:对同一个事件进行监听,忘记移除(removeListener),将造成内存泄漏

解决方案

       最容易出现也是最难排查的就是事件监听造成的内存泄漏,所以事件监听这块需要格外注意小心使用。

       如果出现了内存泄漏问题,需要检测内存使用情况,对内存泄漏的位置进行定位,然后对对应的内存泄漏代码进行修复。

90、HTTP状态消息200 320 304 403 404 500 分别表示什么

200:请求已成功,请求所希望的响应头或数据体将随此响应返回

302:请求的资源临时从不同的URl响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的

304:如果客户端发送了一个带条件的GET请求已被允许,而文档的内容(自己上次访问以来或者根据请求的条件)并没有改变,则服务器应该返回这个状态码。304响应禁止包含消息体,因此始终以消息头后的第一个空行结尾

403:服务器已经理解请求,但是拒绝执行它

404:请求失败,请求所希望得到的资源未被在服务器上发现

500:服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。一般来说,这个问题都会在服务器端的源代码出现错误时出现。

91、闭包是什么,有什么特性,对页面有什么影响?

闭包:"定义在一个函数内部的函数"。当其中一个内部函数在包含它们的外部函数之外被调用时,就会形成闭包。

let fn = (function{
 //局部变量
   var count = 0;
   return function(){
   return ++count;
  }
})()

闭包的特性

  • 封闭性:外界无法访问闭包内部的数据,如果在闭包内声明变量,外界是无法访问的,除非闭包主动向外界提供访问接口
  • 持久性:一般的函数,调用完毕之后,系统自动注销函数,而对于闭包来说,在外部函数被调用之后,闭包结构依然保存在系统中,闭包中的数据依然存在,从而实现对数据的持久使用

优点:

  • 减少全局变量
  • 减少传递函数的参数量
  • 封装

缺点:

  • 使用闭包会占有内存资源,过多使用闭包会导致内存溢出等

92、介绍下Set、Map、WeakSet 和 WeakMap 的区别

  • Set:对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用
  • WeakSet:成员都是对象,成员都是虚弱引用,可以被垃圾回收机制回收,可以用来保存DOM节点,不容易造成内存泄漏
  • Map:本质上是键值对的集合,类似集合,可以遍历,方法很多,可以跟各种数据转换
  • WeakMap:只接受对象作为键名(null除外),不接受其他类型的值作为键名;键名是弱引用,键值可以是任意的,键名所指向的对象可以被垃圾回收,此时键名是无效的;不能遍历,方法有 get、set、has、delete

93、JS异步解决方案的发展历程以及优缺点

  1. 回调函数(callback)

        优点:解决了同步的问题(只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行)

        缺点:回调地狱,不能用 try catch 捕获错误,不能return

     2.Promise

        优点:解决了回调地狱的问题

        缺点:无法取消 Promise,错误需要通过回调函数来捕获

     3.Generator

         特点:可以控制函数的执行,可以配合 co 函数库使用

     4.Async/await

         优点:代码清晰,不用像 Promise 写一大堆 then 链,处理了回调地狱的问题

         缺点:await将异步代码改造成同步代码,如果多个异步操作没有依赖性而使用 await 会导致性能上的降低

94、v-if 与 v-show 的区别

共同点:

都能控制元素的显示与隐藏

不同点:

实现本质方法不同,v-show本质就是通过控制css中的display设置为none,控制隐藏,只会编译一次;v-if是动态的向DOM树内添加或者删除DOM元素,若初始值为false,就不会编译了

而v-if不停的销毁和创建比较消耗性能。总结:如果要频繁切换某节点,使用v-show(切换开销比较小,初始开销较大)

如果不需要频繁切换某节点使用 v-if(初始渲染开销较小,切换开销比较大)

95、Vuex 之 actions 与 mutations 的区别

actions

  • 用于通过提交mutation改变数据
  • 会默认将自身封装为一个Promise
  • 可以包含任意的异步操作

mutations

  • 通过提交commit 改变数据
  • 只是一个单纯的函数
  • 不要使用异步操作,异步操作会导致变量不能追踪

96、Vue中双向数据绑定是如何实现的

  1. vue.js 则是采用数据劫持结合发布者-订阅模式的方式
  2. 通过Object.defineProperty()来劫持各个属性的 setter、getter
  3. 在数据变动时发布消息给订阅者,触发相应的监听回调。我们先来看Object.defineProperty()这个方法:
var obj = {};
Object.defineProperty(obj,'name',{
   get:function(){
      console.log('我被获取了')
      return val;
   },
   set:function(newVal){
       console.log('我被设置了')
   }
})
obj.name = 'fei';
//在给obj设置name属性的时候,触发了set这个方法
var val = obj.name;
//在得到obj的name属性,会触发get方法

97、Vue的两个核心是什么

        1. 数据驱动

         在vue中,数据的改变会驱动视图的自动更新。传统的做法是需要手动改变DOM来使得视图更新,而vue只需要改变数据

          2、组件

          组件化开发,优点很多,可以很好的降低数据之间的耦合度。将常用的代码封装成组件之后(vue组件封装方法),就能高度的复用,提高代码的可重用性。一个页面/模块可以由多个组件所组成。

98、什么是事件冒泡

一个事件触发后,会在子元素和父元素之间传播,这种传播分为三个阶段:

  • 捕获阶段:(从window对象传导到目标节点(从外到里),这个阶段不会响应任何事件)
  • 目标阶段:(在目标节点上触发)
  • 冒泡阶段:(从目标节点传导回window对象(从里到外),事件委托/事件代理就是利用事件冒泡机制把里层需要响应的事件绑定到外层)

99、ES6新特性

       const 和 let、模板字符串、箭头函数、函数的参数默认值、对象和数组解构、for...of 和 for...in、ES6中的类

100、Let 与 var 与 const 的区别

  • Var声明的变量会挂载在window上,而let和const声明的变量不会
  • Var声明的变量存在变量提升,let和const不存在变量提升
  • 同一作用域下 var 可以声明同名变量,let 和 const 不可以
  • Let和const声明会形成块级作用域
  • Let暂存死区
  • Const一旦声明,必须赋值,不能用null占位,声明后不能再修改,如果声明的是复合类型数据,可以修改属性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值