哭了,我以为刷刷前端面试题高频考点就够了,没想到面试官还会深挖问题问

李不要熬夜 2021-06-16 14:03:13
面试 程序员 前端 Vue.js SegmentFault


前言

逛网站时看到个网友在说,自己面试时被问到了刷到的题目当时很开心,信心满满的回答,但紧接着下一秒就笑不出来了,以为面试官是换问题问了,没想到在这个问题基础上发问,这让他就有点措手不及了,回答的支支吾吾的。其实面试官会继续在这问题上“不放过”你,也是看你理解并掌握的是有多深。一道大众题谁都会,这分辨不出个什么,但要是深挖下的问题,这技术也能看的出十七八九,所以也并不是专门去刁钻,面试官问的越深,你回答的稳,面试官可不得喜欢你。碰到这种情况不见得多,但小编还是整理些在高频考点上深挖的题目,小伙伴们看看心里有个底,题目都是带有答案的。

面试题高频考点

var、let和const的区别

1、作用域不同(是否含有块级元素)

  • 块级作用域:声明的变量只在该代码块作用域内有效
  • var没有块级作用域,let、const有块级作用域

2、是否存在暂时性死区

  • let和const定义的变量是存在暂时性死区的,而var没有,原理如下:
  • 对于var而言,当进入var变量的作用域时,会立即为它创建存储空间,并对它进行初始化,赋值为undefined,当函数加载到变量声明语句时,会根据语句对变量赋值。
  • 而let和const却不一样,当进入let变量的作用域时,会立即给它创建存储空间,但是不会对它进行初始化

3、是否存在变量提升

  • 变量提升:变量在声明之前可以使用
  • var声明的变量存在变量提升,let、const不存在变量提升

4、能否重复声明

  • var声明的可以重复声明, let 和const声明的不可以重复声明

5、变量能否被修改

  • var、let声明的变量可以被修改,const声明的常量不可修改

    面试官深挖的问题

    1.那么var是什么作用域呢?这个我在面试的时候就被问到过,那么你知道吗?
    var的作用域是在被定义的时候决定的,如下:

  • 在函数内部定义的话,那么var就是局部变量,其作用域称为函数作用域/局部作用域
  • 在函数外部定义的话,那么var就是全局变量,其作用域称为全局作用域

2.变量提升和函数提升的相关问题

//1
var a = 1;
function b(){
var a = 2;
console.log(a) //输出的是什么 为什么
}
b()
//2
var a = 1;
function a(){
}
console.log(a) //输出的是什么 为什么
//3
var a = 1;
function a(){
console.log(a);
}
a()//输出的是什么 为什么
  • 首先第一个输出的是2,这个涉及的就是作用域问题,因为在b()内部定义变量a,所有先访问函数内部的变量a,所有输出的是2,如果函数内部没有定义变量a,那么就访问全局中定义的a,输出的机会是1
  • 第二个输出的是1,这里隐藏了变量提升和函数提升的优先级,函数声明提升>变量声明提升.当js解析器在遇到函数声明时,会优先将其提升到定义体顶部,其次再是var声明的变量,这样就导致函数a被变量a给覆盖的情况,所以最终将打印1。
  • 第三个输出的是TypeError: a is not a function,这个和第二个类似,函数a被变量a给覆盖,所以当调用a()的时候,就会报错因为a只是一个变量了。

3.const声明的常量不可以改变=>const声明的对象属性是否可以改变?

const obj = {
name:"大海",
age: 18
}
obj.age = 20;
console.log(`name:${obj.name},age:${obj.age}`);
//输出 name:大海,age:20

因为对象是引用类型的,obj中保存的仅是对象的指针,这就意味着,const仅保证指针不发生改变,修改对象的属性不会改变对象的指针,所以是被允许的。也就是说const定义的引用类型只要指针不发生改变,其他的不论如何改变都是允许的。

const obj = {
name:"大海",
age: 18
}
// obj.age = 20;
// console.log(`name:${obj.name},age:${obj.age}`);
obj={name:"大海",age:18}
console.log(`name:${obj.name},age:${obj.age}`);

即使对象的内容没改变,指针改变了也是不可以的

箭头函数和普通函数的区别

  • 箭头函数不需要 function 关键字来创建函数
  • 箭头函数可以省略 return 关键字
  • 箭头函数继承当前上下文的 this 关键字,定义的时候就确定并固定了
  • 箭头函数call、apply、bind 并不会影响其 this 的指向
  • 箭头函数没有原型prototype
  • 箭头函数没有自己的arguments

    面试官深挖的问题

    1.call、apply和bind的区别

  • 三者都可以改变函数的this指向,通过第一个参数来绑定
  • 三者的第一个参数如果为null、undefined的时候,默认指向window(在浏览器中)
  • call第二个参数是参数列表,applay是数组,bind传入的也是一个参数列表(但是这个参数列表可以分多次传入,apply和call是一次性传入所有参数)
  • bind 改变this指向后不会立即执行,而是返回一个永久改变this指向的函数来让我们手动调用; apply, call则是立即调用

2.箭头函数的this是怎么确定的

var name = '小度'
function b(){
console.log(this); // window
var name = '小白'
c =()=>{
console.log(this.name) ;
}
c()
}
b()

这里箭头函数c是在普通函数b中定义的,所以箭头函数c的this是指向普通函数b的this的,这里普通函数的this是全局(window),这个需要在浏览器环境下执行,在node环境下执行是undefined

Promise的静态方法和实例方法

注:这里有些公司会涉及手写Promise,大家可以去研究源码实现和手写一下。这个知识点很重要,高频考点中高频考点,大家一定要注意了啊!

1.首先了解Promise的三种状态

  • pending 待定
  • fulfilled/resolved 兑现/解决/成功
  • rejected 拒绝/失败

2.Promise对象的状态改变,只有两种可能:

  • 从pending变为fulfilled
  • 从pending变为rejected

    注意:这两种情况只要发生,状态就确定了,不会再变了。

【静态方法】

  • 1.Promise.resolve
    resolve : 将Promise对象的状态从 Pending(待定) 变为 Fulfilled(成功)

    new Promise(resolve => {
    resolve('hello 大海')
    }).then(res => {
    console.log(res)
    })
  • 2.Promise.reject
    reject : 将Promise对象的状态从 Pending(待定) 变为 Rejected(失败)

    new Promise(reject => {
    reject('hello 大海')
    }).then(res => {
    console.log(res)
    })
  • 3.Promise.all

    • 比如当数组里的p1,p2,p3,p4都执行完成时,页面才显示。
    • 值得注意的是,返回的数组结果顺序不会改变,即使P2的返回要比P1的返回快,顺序依然是p1,p2,p3,p4
    • Promise.all成功返回成功数组,失败返回失败数据,一但失败就不会继续往下走
     let p1 = Promise.resolve('p1')
    let p2 = Promise.resolve('p2')
    let p3 = Promise.resolve('p3')
    let p4 = Promise.resolve('p4')
    Promise.all([p1, p2, p3, p4]).then(res => {
    console.log('成功', res); //返回数组
    }).catch(err => {
    console.log('失败', err);
    })
    
  • 4.Promise.race
    Promise.race是赛跑的意思,也就是说Promise.race([p1, p2, p3,p4])里面的结果哪个获取的快,就返回哪个结果,不管结果本身是成功还是失败

    let p1 = Promise.resolve('p1')
    let p2 = Promise.resolve('p2')
    let p3 = Promise.reject('p3')
    let p4 = Promise.resolve('p4')
    Promise.race([p1, p2, p3, p4]).then(res => {
    console.log('成功', res); //返回数组
    }).catch(err => {
    console.log('失败', err);
    })
  • 5.Promise.allSettled //ES11的新特性

    • 该方法返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的promise结果。
    • 当您有多个彼此不依赖的异步任务成功完成时,或者您总是想知道每个promise的结果时,通常使用它。

      const promise1 = Promise.resolve(3);
      const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));
      const promises = [promise1, promise2];
      Promise.allSettled(promises).
      then((results) => results.forEach((result) => console.log(result.status)));

      【实例方法(原型方法)】

  • 1.Promise.prototype.then
    该方法可以接收两个回调函数作为参数,其中第二个回调函数是可选的。第一个回调函数是 Promise 对象的状态变为 Resolved 时调用,第二个回调函数是 Promise 对象的状态变为 Rejected 时调用。

    var p1 = new Promise((resolve, reject) => {
    resolve('成功!');
    // or
    // reject(new Error("出错了!"));
    });
    p1.then(value => {
    console.log(value); // 成功!
    }, reason => {
    console.error(reason); // 出错了!
    });
  • 2.Promise.prototype.catch
    该方法返回一个Promise,并且只处理拒绝(rejected )的情况。

    const p = new Promise((resolve, reject)=>{
    reject('失败了')
    }).catch(err=>{
    console.log(err);
    })
    
  • 3.Promise.prototype.finally
    该方法,无论上一个promise 成败都会执行,且默认情况下会原样传递上一个 promise 的决议,但是finally 对自身返回的 promise 的决议影响有限,它可以将上一个 resolve 改为 reject,也可以将上一个 reject 改为另一个 reject,但不能把上一个 reject 改为 resolve。

【默认情况】

var p = Promise.resolve('ok')
.finally((res) => {
return res })
.then(value => {
console.log('成功', value)
}, (err) => {
console.log('失败', err)
});

【将上一个 resolve 改为 reject】

var p = Promise.resolve('ok')
.finally(() => {
return Promise.reject('err') })
.then(value => {
console.log('成功', value)
}, (err) => {
console.log('失败', err)
});

面试官深挖的问题

then有几个参数,then第二个参数和catch的区别是什么?
then方法可以接受两个回调函数作为参数。其中,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。then方法返回的是一个实例(不是原来那个Promise实例)

【区别】

  • 区别1:最主要区别就是then中第一个函数里抛出的异常,它的第二个函数是捕获不到异常的,后面的catch可以捕获到(或者第二个then的第二个函数也可以捕获到);
  • 区别2:且then的第二个参数和catch捕获异常时会采取就近原则,当两者都存在时,则只有then的第二个参数能捕获到,如果then的第二个参数不存在,则catch方法会捕获到;

【用代码展示一下then第二个参数和catch的区别】

const p = new Promise((resolve, reject)=>{
resolve('对了')
})
p.then((res)=>{
throw new Error('hello');
},(err)=>{
console.log(err,'第一个then捕获错误');
}).catch((err1)=>{
console.log(err1,'catch捕获错误');
})

我们可以发现then中的第二个函数无法捕获到自身第一个函数抛出的异常,catch则可以捕获的得到,如果把catch删除,那么就会报错


const p = new Promise((resolve, reject)=>{
resolve('成功了')
})
p.then((res)=>{
throw new Error('hello');
},(err)=>{
console.log(err,'第一个then捕获错误');
})

也可以在继续使用then来捕获上一个then中抛出的错误

const p = new Promise((resolve, reject)=>{
resolve('成功了')
})
p.then((res)=>{
throw new Error('hello');
},(err)=>{
console.log(err,'第一个then捕获错误');
}).then((res)=>{},(err1)=>{
console.log(err1,'第二个then捕获错误');
})

就近原则捕获异常,就是区别2

const p = new Promise((resolve, reject)=>{
resolve('成功了')
})
p.then((res)=>{
throw new Error('hello');
},(err)=>{
console.log(err,'第一个then捕获错误');
}).then((res)=>{},(err1)=>{
console.log(err1,'第二个then捕获错误');
}).catch((err2)=>{
console.log(err2,'catch捕获错误');
})

Promise.all和 Promise.race的区别

【区别】

  • Promise.all成功返回成功数组,失败返回失败数据,一但失败就不会继续往下走
  • Promise.race是赛跑的意思,也就是说Promise.race([p1, p2, p3,p4])里面的结果哪个获取的快,就返回哪个结果,不管结果本身是成功还是失败

【Promise.all】

 let p1 = Promise.resolve('p1')
let p2 = Promise.resolve('p2')
let p3 = Promise.reject('p3')
let p4 = Promise.resolve('p4')
Promise.all([p1, p2, p3, p4]).then(res => {
console.log('成功', res); //返回数组
}).catch(err => {
console.log('失败', err);
})

【Promise.race】

 let p1 = Promise.reject('p1')
let p2 = Promise.resolve('p2')
let p3 = Promise.reject('p3')
let p4 = Promise.resolve('p4')
Promise.race([p1, p2, p3, p4]).then(res => {
console.log('成功', res); //返回数组
}).catch(err => {
console.log('失败', err);
})

Promise与setTimeout结合猜输出

console.log('start')
setTimeout(() => {
console.log('time')
})
Promise.resolve().then(() => {
console.log('resolve')
})
console.log('end')

【分析】

  • 刚开始整个脚本作为一个宏任务来执行,对于同步代码直接压入执行栈进行执行,因此先打印出start和end。
  • setTimout作为一个宏任务被放入宏任务队列(下一个)
  • Promise.then作为一个微任务被放入微任务队列
  • 本次宏任务执行完,检查微任务,发现Promise.then,执行它
  • 接下来进入下一个宏任务,发现setTimeout,执行。
    篇幅有限没有列举更多的前端面试题,小编把整理的前端大厂面试题PDF分享出来,一共有269页,只需要点击即可免费领取,下面是面试题文档的部分展示。

    为什么会深挖问题?

    其实上面的问题说难不难,说简单也确实不简单。面试官需要的答案总是比你能回答的要再更深一步。不用太多,只一步。

只知道“旧页面传值给新页面”,不够!需要知道:如何处理“新页面回传给旧页面且考虑新页面崩溃情况”?

只知道“Object.defineproperty()”,不够!需要知道:如何监控 DOM 新属性的增加?

只知道“懒加载的滚动监听”,不够!需要知道:懒加载的其它实现方式呢?

只知道“PerformanceTiming API”,不够!需要知道:具体是如何做差,各监控指标的差异在哪,图片资源加载到底如何计时?

呜呼!这算“面试造火箭,工作拧螺丝” 吗?

未必!这些问题在实际工作中是极大可能遇到的,本瓜之前就用过监听本地缓存。PerformanceTiming 更是性能监控的良方,都是为了做出更好的 Web 服务,为什么拒绝呢?

版权声明
本文为[李不要熬夜]所创,转载请带上原文链接,感谢
https://segmentfault.com/a/1190000040182276

  1. HTML + CSS + JavaScript to achieve cool Fireworks (cloud like particle text 3D opening)
  2. HTML + CSS + JavaScript realizes 520 advertising love tree (including music), which is necessary for programmers to express themselves
  3. Solve the problem of Web front-end deployment server (it can be deployed online without a server)
  4. HTML + CSS + JS make wedding countdown web page template (520 / Tanabata Valentine's Day / programmer advertisement)
  5. What else can driverless minibus do besides "Park connection"?
  6. Cloud native leads the era of all cloud development
  7. NRM mirror source management tool
  8. Bring it to you, flex Jiugong
  9. Lolstyle UI component development practice (II) -- button group component
  10. Deconstruction assignment in ES6
  11. Luo 2 peerless Tang clan was officially launched. The official gave a key point, and the broadcast time was implied
  12. 20初识前端HTML(1)
  13. 当新零售遇上 Serverless
  14. 20 initial knowledge of front-end HTML (1)
  15. When new retail meets serverless
  16. [golang] - go into go language lesson 5 type conversion
  17. [golang] - go into go language lesson 6 conditional expression
  18. HTML5(八)——SVG 之 path 详解
  19. HTML5 (8) -- detailed explanation of SVG path
  20. 需要开通VIP以后页面内容才能复制怎么办?控制台禁用javascript即可
  21. Web前端|CSS入门教程(超详细的CSS使用讲解,适合前端初学者)
  22. 实践积累 —— 用Vue3简单写一个单行横向滚动组件
  23. Serverless 全能选手,再下一城
  24. What if you need to open a VIP to copy the page content? Just disable JavaScript on the console
  25. Web front end | CSS introductory tutorial (super detailed CSS explanation, suitable for front-end beginners)
  26. Practice accumulation - write a single line horizontal scroll component simply with vue3
  27. Dili Reba is thin again. She looks elegant and high in a strapless hollow skirt, and her "palm waist" is beautiful to a new height
  28. Serverless all-round player, next city
  29. The difference between MySQL semi synchronous replication and lossless semi synchronous replication
  30. Vue表单设计器的终极解决方案
  31. The ultimate solution for Vue form designer
  32. Nginx从理论到实践超详细笔记
  33. Yu Shuxin's red backless swimsuit is split to the waist and tail, with a concave convex figure and excessive color matching, and his face is white to dazzling
  34. Nginx ultra detailed notes from theory to practice
  35. 【动画消消乐|CSS】086.炫酷水波浪Loading过渡动画
  36. typecho全站启用https
  37. CCTV has another popular employee. The off-site interpretation is very professional, and the appearance ability is no less than that of Wang Bingbing
  38. [animation Xiaole | CSS] 086. Cool water wave loading transition animation
  39. Enable HTTPS in Typecho
  40. 50天用JavaScript完成50个web项目,我学到了什么?
  41. 根据JavaScript中原生的XMLHttpRequest实现jQuery的Ajax
  42. What have I learned from completing 50 web projects with JavaScript in 50 days?
  43. "My neighbor doesn't grow up" has hit the whole network. There are countless horse music circles, and actor Zhou Xiaochuan has successfully made a circle
  44. 根据JavaScript中原生的XMLHttpRequest实现jQuery的Ajax
  45. Implement the Ajax of jQuery according to the native XMLHttpRequest in JavaScript
  46. Implement the Ajax of jQuery according to the native XMLHttpRequest in JavaScript
  47. 30 + women still wear less T-shirts and jeans. If they wear them like stars, they will lose weight
  48. 数栈技术分享前端篇:TS,看你哪里逃~
  49. Several stack technology sharing front end: TS, see where you escape~
  50. 舍弃Kong和Nginx,Apache APISIX 在趣链科技 BaaS 平台的落地实践
  51. Abandon the landing practice of Kong and nginx, Apache apisik on the baas platform of fun chain technology
  52. 浪迹天涯king教你用elementui做复杂的表格,去处理报表数据(合并表头,合并表体行和列)
  53. 前端HTML两万字图文大总结,快来看看你会多少!【️熬夜整理&建议收藏️】
  54. Wandering around the world king teaches you to use elementui to make complex tables and process report data (merge header, merge table body rows and columns)
  55. 路由刷新数据丢失 - vuex数据读取的问题
  56. Front end HTML 20000 word graphic summary, come and see how much you can【 Stay up late to sort out & suggestions]
  57. Route refresh data loss - vuex data reading problem
  58. Systemctl系统启动Nginx服务脚本
  59. Systemctl system startup nginx service script
  60. sleepless