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关键字创建流程
- 在内存中创建一个新的空对象
- 让this指向这个新的对象
- 执行构造函数里面的代码,给这个新对象添加属性和方法(给对象赋值)
- 返回这个新对象(所以构造函数里面不需要return)
66、构造函数 原型对象 实例对象三者的关系
- 创建构造函数时,系统自动分配一个原型对象,构造函数种的prototype属性,指向这个原型对象
- 原型对象中的constructor属性,指向它的构造函数
- 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、如何实现浏览器内多个标签页之间的通信
实现多个标签页之间的通信,本质上都是通过中介者模式来实现的。因为标签页之间没有办法直接通信,因此我们可以找一个中介者来让标签页和中介者进行通信,然后让这个中介者进行消息的转发。
- 使用Websocket,通信的标签页连接同一个服务器,发送消息到服务器后,服务器推送消息给多有连接的客户端
- 可以调用localStorage,localStorage在另一个浏览上下文里被添加、修改或删除时,它都会触发一个storage事件,我们可以通过监听storage事件,控制它的值来进行页面信息通信
- 如果我们能够获得对应标签页的引用,通过postMessage方法也是可以实现多个标签页通信的
85、简述伪类和伪元素
伪类:
伪类用于当已有元素处于某种状态时,为其添加对应的样式,这个状态是根据用户行为变化而变化的。比如说:hover。它只有处于dom树无法描述的状态才能为元素添加样式,所以称为伪类。
伪元素:
伪元素用于创建一些原本不在文档树中的元素,并为其添加样式,比如说::before。虽然用户可以看到这些内容,但是其实他不在文档树种。
区别:
伪类的操作对象是文档
86、Vue的父组件和子组件生命周期钩子执行顺序是什么
- 加载渲染过程:父 beforeCreate -> 父 created -> beforeMount ->子 beforeCreate ->子 created ->子 beforeMount -> mounted ->父 mounted
- 子组件更新过程:父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
- 父组件更新过程:父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
- 销毁过程:父 beforeDestroy -> 子 beforeDestroy ->子 destroyed -> 父 destroyed
87、Vue中 computed 和 watch 的差异
- computed 是计算一个新的属性,并将该属性挂在到Vue实例上,而watch是监听已经存在且已挂载到Vue实例上的数据,所以用watch同样可以监听computed 计算属性的变化
- computed 本质是一个惰性求值的观察者,具有缓存性,只有当依赖变化后,第一次访问computed 值,才会计算新的值。而watch则是当数据发送变化便会调用执行函数
- 从使用场景上来说,computed适用一个数据被多个数据影响,而watch使用一个数据影响多个数据
88、webpack 中 loader 和 plugin 的区别是什么
loader:loader是一个转换器,将A文件进行编译成B文件,属于单纯的文件转换过程;
plugin:plugin是一个扩展器,它丰富了webpack本身,针对是loader结束后,webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听webpack打包过程中的某些节点,执行广泛的任务。
89、Node中的内存泄露问题和解决方案
内存泄漏的原因
- 全局变量:全局变量挂在 root 对象上,不会被清除掉
- 闭包:如果闭包未释放,就会导致内存泄漏
- 事件监听:对同一个事件进行监听,忘记移除(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异步解决方案的发展历程以及优缺点
- 回调函数(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中双向数据绑定是如何实现的
- vue.js 则是采用数据劫持结合发布者-订阅模式的方式
- 通过Object.defineProperty()来劫持各个属性的 setter、getter
- 在数据变动时发布消息给订阅者,触发相应的监听回调。我们先来看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占位,声明后不能再修改,如果声明的是复合类型数据,可以修改属性。
本文汇总了前端面试中常见的100道JavaScript核心知识点,包括处理异步的方法(回调、Promise、async/await)、JS弹出框、URL编码解码、日期转换、BOM与DOM、数据类型转换、懒加载、setTimeout与setInterval的区别、闭包、原型链、HTTP状态码、事件冒泡等。通过深入理解这些知识点,能够帮助开发者更好地应对前端面试和日常开发。

被折叠的 条评论
为什么被折叠?



