前端面试会问些啥---看哪些是你的知识盲点?
1、说一说promise的理解,通常怎么用?
Promise是最早由社区提出和实现的一种解决异步编程的方案,比其他传统的解决方案(回调函数和事件)更合理和更强大。promise是为解决异步处理回调金字塔问题而产生的。Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。
引自:https://www.jianshu.com/p/002003a38e89
2、如果有4个接口请求,我需要等4个请求完毕之后再做下一步操作,该如何做?在我们的异步调用时经常有这样一种场景:我们需要同时调用多个异步操作,但希望只有等所有的操作都完成后,我们才去执行响应操作
Promise.all 方法
参数:接受一个数组,数组内都是Promise实例
返回值:返回一个Promise实例,这个Promise实例的状态转移取决于参数的Promise实例的状态变化。当参数中所有的实例都处于resolve状态时,返回的Promise实例会变为resolve状态。如果参数中任意一个实例处于reject状态,返回的Promise实例变为reject状态
3、Vue中computed和watch的区别?
计算属性(computed):对于任何复杂逻辑,你都应当使用计算属性。计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。
侦听器(watch):Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
总结:
(1)如果一个数据依赖于其他数据的简易计算处理的,那么使用computed比较合适。
(2)如果需要在某个数据变化时做一些事情,使用watch来观察这个数据变化
4、说一说es6中的一些常用函数。怎样数组去重等等?es5和es6的区别。
filter() 方法:创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素
includes() 方法:用来判断一个数组是否包含一个指定的值,如果是返回true,否则false。
some() 方法:用于检测数组中的元素是否满足指定条件(函数提供)
findIndex():返回(传入函数)符合条件的数组第一个元素位置,为数组中的每个元素都调用一次函数执行
数组去重的5种方法:
(1)双重for循环去重
原理 两两比较如果相等的话就删除第二个
例如: 1 1 1 3 2 1 2 4
先让第一个1 即arr[0]与后面的一个个比较 如果后面的值等于arr[0] 删除后面的值
第一次结束后的结果是 1 3 2 2 4 删除了后面所有的1
同理 第二次 第三会删除与自己相同的元素
因此我们可以很好的利用这个属性 当返回的是 -1时 就让其存入数组
(2)单层for循环
先排序让大概相同的在一个位置,两两比较 一样删除后面的,i--
(3)用一个空数组去存首次 出现的元素
利用 indexOf 属性 indexOf是返回某个指定的字符在字符串中出现的位置,如果没有就会返回-1
(4)利用对象的思想 如果对象里没有这个属性的话就会返回undefined
(5)循环比较如果相等的让后面的元素值为0 最后在输出的时候删除为0的 这个前提是你的数据里不能有0 但是凡事可以变通你可以设置任何值替代这个0 这个方法是我当时想到实现的所以没有进行很好的优化
(6)Array.from(new Set(arr))
原文链接:https://blog.csdn.net/qq_42489540/article/details/81671312
es5和es6的区别:
ECMAScript6在保证向下兼容的前提下,提供大量新特性,目前浏览器兼容情况如下:
ES6特性如下:
(1)块级作用域 关键字let, 常量const
(2)对象字面量的属性赋值简写(property value shorthand)
(3)赋值解构
(4)箭头函数
简化了代码形式,默认return表达式结果。
自动绑定语义this,即定义函数时的this。
(5)Promises
5、怎样结束一个网络请求?如何终止前端发起的请求?
问题案例:
(1)一些列表页接口比较慢,改变查询条件后发送查询请求,这样就和上次的查询请求形成两个异步请求,有时可能就会发生本次请求先得到响应数据,然后上一次请求后得到响应数据,这样在页面上的查询结果就会出现bug。(不是单纯的防抖和节流就能解决问题)
(2)一些大文件上传,需要很久的时间,用户在中途想要终止上传
问题解决:
(1)【原生JS】XMLHttpRequest.abort();
如果该请求已被发出,XMLHttpRequest.abort()方法将终止该请求。当一个请求被终止,它的 readyState 属性将被置为0(UNSENT)。
(2)【Ajax】ajax.abort();
(3)【axios】axios.CancelToken;
Axios 提供了一个 CancelToken的函数,这是一个构造函数,该函数的作用就是用来取消接口请求的。利用axios请求的config参数,向axios添加一个包含cancelToken的config配置对象。
(4)【微信小程序 】RequestTask.abort();
原文链接:https://blog.csdn.net/qq_41887214/article/details/105752554
6、JavaScript中apply、call、bind的区别。
在JS中,这三者都是用来改变函数的this对象的指向的,他们有什么样的区别呢。
在说区别之前还是先总结一下三者的相似之处:
(1)都是用来改变函数的this对象的指向的。
(2)第一个参数都是this要指向的对象。
(3)都可以利用后续参数传参。
区别:
var xw = {
name : "小王",
gender : "男",
age : 24,
say : function() {
alert(this.name + " , " + this.gender + " ,今年" + this.age);
}
}
var xh = {
name : "小红",
gender : "女",
age : 18
}
xw.say();
xw.say.call(xh);
xw.say.apply(xh);
xw.say.bind(xh)();
call和apply都是对函数的直接调用,而bind方法返回的仍然是一个函数,因此后面还需要()来进行调用才可以。
var xw = {
name : "小王",
gender : "男",
age : 24,
say : function(school,grade) {
alert(this.name + " , " + this.gender + " ,今年" + this.age + " ,在" + school + "上" + grade);
}
}
var xh = {
name : "小红",
gender : "女",
age : 18
}
xw.say.call(xh,"实验小学","六年级");
xw.say.apply(xh,["实验小学","六年级"]);
xw.say.bind(xh,"实验小学","六年级")();
xw.say.bind(xh)("实验小学","六年级");
原文链接:https://www.cnblogs.com/cosiray/p/4512969.html
7、说一说你对封装、继承、多态的了解。
面向对象三大基本特性。
所谓封装:
也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。封装是面向对象的特征之一,是对象和类概念的主要特性。 简单的说,一个类就是一个封装了数据以及操作这些数据的代码的逻辑实体。在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问。通过这种方式,对象对内部数据提供了不同级别的保护,以防止程序中无关的部分意外的改变或错误的使用了对象的私有部分。
所谓继承:
是指可以让某个类型的对象获得另一个类型的对象的属性的方法。它支持按级分类的概念。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”。继承的过程,就是从一般到特殊的过程。要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。继承概念的实现方式有二类:实现继承与接口继承。实现继承是指直接使用基类的属性和方法而无需额外编码的能力;接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力;
所谓多态:
就是指一个类实例的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。
8、浏览器加载页面时都做了什么?浏览器是如何渲染页面的?
DNS解析
TCP连接
发送HTTP请求
服务器处理请求并返回HTTP报文
浏览器解析渲染页面
连接结束
详细解析:输入url后,首先需要找到这个url域名的服务器ip,为了寻找这个ip,浏览器首先会寻找缓存,查看缓存中是否有记录,缓存的查找记录为:浏览器缓存-》系统缓存-》路由器缓存,缓存中没有则查找系统的hosts文件中是否有记录,如果没有则查询DNS服务器,得到服务器的ip地址后,浏览器根据这个ip以及相应的端口号,构造一个http请求,这个请求报文会包括这次请求的信息,主要是请求方法,请求说明和请求附带的数据,并将这个http请求封装在一个tcp包中,这个tcp包会依次经过传输层,网络层,数据链路层,物理层到达服务器,服务器解析这个请求来作出响应,返回相应的html给浏览器,因为html是一个树形结构,浏览器根据这个html来构建DOM树,在dom树的构建过程中如果遇到JS脚本和外部JS连接,则会停止构建DOM树来执行和下载相应的代码,这会造成阻塞,这就是为什么推荐JS代码应该放在html代码的后面,之后根据外部央视,内部央视,内联样式构建一个CSS对象模型树CSSOM树,构建完成后和DOM树合并为渲染树,这里主要做的是排除非视觉节点,比如script,meta标签和排除display为none的节点,之后进行布局,布局主要是确定各个元素的位置和尺寸,之后是渲染页面,因为html文件中会含有图片,视频,音频等资源,在解析DOM的过程中,遇到这些都会进行并行下载,浏览器对每个域的并行下载数量有一定的限制,一般是4-6个,当然在这些所有的请求中我们还需要关注的就是缓存,缓存一般通过Cache-Control、Last-Modify、Expires等首部字段控制。 Cache-Control和Expires的区别在于Cache-Control使用相对时间,Expires使用的是基于服务器 端的绝对时间,因为存在时差问题,一般采用Cache-Control,在请求这些有设置了缓存的数据时,会先 查看是否过期,如果没有过期则直接使用本地缓存,过期则请求并在服务器校验文件是否修改,如果上一次 响应设置了ETag值会在这次请求的时候作为If-None-Match的值交给服务器校验,如果一致,继续校验 Last-Modified,没有设置ETag则直接验证Last-Modified,再决定是否返回304
9、Vue中双向数据绑定是怎么操作的?vue的双向数据绑定原理是什么。
采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
首先我们为每个vue属性用Object.defineProperty()实现数据劫持,为每个属性分配一个订阅者集合的管理数组dep;然后在编译的时候在该属性的数组dep中添加订阅者,v-model会添加一个订阅者,{{}}也会,v-bind也会,只要用到该属性的指令理论上都会,接着为input会添加监听事件,修改值就会为该属性赋值,触发该属性的set方法,在set方法内通知订阅者数组dep,订阅者数组循环调用各订阅者的update方法更新视图。
10、说一说你对单页应用的理解,要是你不用Vue,自己来写一个单页应用,应该怎么写?
11、Vue中一个页面怎样定义内部样式,不会影响其它页面?
12、说一说你对闭包的理解。写一个闭包函数?
闭包函数是指有权访问另一个函数作用域中的变量的函数
创建闭包函数最常见的方式是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量
闭包的特点:1函数嵌套函数,
函数内部可以引用外部的参数和变量
参数和变量不会被垃圾回收机制回收
闭包的优点:
希望一个变量长期驻扎在内存中*
避免全局变量的污染*
私有变量存在
闭包的实现
函数嵌套函数*
外层函数返回内层函数
外面有一全局变量接受外层函数
13、通常调用后端用axios的请求,可以不用axios,自己来写一个嘛?
14、js的原型和原型链。
15、js的作用域和作用域链。
16、如何在Vue中建立全局引用或者全局命令?
更多前端面试题,以及以上大部分问题的答案都可以参考:https://note.youdao.com/ynoteshare1/index.html?id=59459d9adcf7326b888c3540e25887c6&type=note