前端面试题

222 阅读8分钟

1 从输入一个 URL 地址到浏览器完成渲染的整个过程

这个问题属于老生常谈的经典问题了 下面给出面试简单版作答

  1. 浏览器地址栏输入 URL 并回车
  2. 浏览器查找当前 URL 是否存在缓存,并比较缓存是否过期
  3. DNS 解析 URL 对应的 IP
  4. 根据 IP 建立 TCP 连接(三次握手)
  5. 发送 http 请求
  6. 服务器处理请求,浏览器接受 HTTP 响应
  7. 浏览器解析并渲染页面
  8. 关闭 TCP 连接(四次握手)

注意! 面试官可以基于这道题进行前端很多知识点的考察 从 http 网络知识到浏览器原理再到前端性能优化 这个题目都可以作为引子开始

所以推荐大家可以看看这篇详细作答 史上最详细的经典面试题 从输入 URL 到看到页面发生了什么?

摘自juejin.cn/post/700463…

2 什么是事件代理(事件委托) 有什么好处

事件委托的原理:不给每个子节点单独设置事件监听器,而是设置在其父节点上,然后利用冒泡原理设置每个子节点。

优点:

  • 减少内存消耗和 dom 操作,提高性能 在 JavaScript 中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断的操作 dom,那么引起浏览器重绘和回流的可能也就越多,页面交互的事件也就变的越长,这也就是为什么要减少 dom 操作的原因。每一个事件处理函数,都是一个对象,多一个事件处理函数,内存中就会被多占用一部分空间。如果要用事件委托,就会将所有的操作放到 js 程序里面,只对它的父级进行操作,与 dom 的操作就只需要交互一次,这样就能大大的减少与 dom 的交互次数,提高性能;
  • 动态绑定事件 因为事件绑定在父级元素 所以新增的元素也能触发同样的事件

3 事件循环

Event Loop即事件循环,是指浏览器或Node的一种解决javaScript单线程运行时不会阻塞的一种机制,也就是我们经常使用异步的原理。

JS执行过程中除依靠函数调用栈来搞定函数执行顺序外,还依靠队列来搞定另外一些代码的执行,整个过程为事件循环过程。

一个线程中事件循环事唯一的,但是任务队列可以拥有多个。任务队列可以分为宏任务和微任务。

  • 而宏任务一般是:包括整体代码script,setTimeout,setInterval、setImmediate。

  • 微任务:原生Promise(有些实现的promise将then方法放到了宏任务中)、process.nextTick、Object.observe(已废弃)、 MutationObserver 记住就行了。

参考juejin.cn/post/684490…

4 addEventListener 默认是捕获还是冒泡

默认是冒泡

addEventListener第三个参数默认为 false 代表执行事件冒泡行为。

当为 true 时执行事件捕获行为。

5 promise 

JS 是单线程的,浏览器是多线程的。

为使浏览器具有异步操作,即定时器,请求,事件监听。可以通过事件循环处理。

promise.then 解决回调地狱问题

promise.catch

promise.race; 多个任务同时执行,返回最先结束的的结果,不管是否失败

promise.all;    多个任务同时执行,以数组返回所以结果,如果有一个任务rejected,则只返回                          rejected任务的结果

promise.reslove

6 promise 与async await

promise 是链式操作可以自己catch 异常; async 要在函数内catch异常

promise 有并行神器,如promise.all/promise.race

promise 是显示异步;async/await 可以让代码看起来同步

7 apply call bind 区别

  • 三者都可以改变函数的 this 对象指向。
  • 三者第一个参数都是 this 要指向的对象,如果如果没有这个参数或参数为 undefined 或 null,则默认指向全局 window。
  • 三者都可以传参,但是 apply 是数组,而 call 是参数列表,且 apply 和 call 是一次性传入参数,而 bind 可以分为多次传入
  • bind 是返回绑定 this 之后的函数,便于稍后调用;apply 、call 则是立即执行 。
  • bind()会返回一个新的函数,如果这个返回的新的函数作为构造函数创建一个新的对象,那么此时 this 不再指向传入给 bind 的第一个参数,而是指向用 new 创建的实例

注意!很多同学可能会忽略 bind 绑定的函数作为构造函数进行 new 实例化的情况

8 改变this 指向 

  • 使用 ES6 的箭头函数
  • 在函数内部使用 _this = this
  • 使用 applycallbind
  • new 实例化一个对象
  • 箭头函数的 this 始终指向函数定义时的 this,而非执行时。 ,箭头函数需要记着这句话:“箭头函数中没有 this 绑定,必须通过查找作用域链来决定其值,如果箭头函数被非箭头函数包含,则 this 绑定的是最近一层非箭头函数的 this,否则,this 为 undefined”。
  • 摘自 juejin.cn/post/684490…

9 箭头函数

摘自:juejin.cn/post/698356…

10 防抖 节流

  • 函数防抖和函数节流都是防止某一时间频繁触发,但是这两兄弟之间的原理却不一样。
  • 函数防抖是某一段时间内只执行一次,而函数节流是间隔时间执行。

结合应用场景

  • debounce

    • search搜索联想,用户在不断输入值时,用防抖来节约请求资源。
    • window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次
  • throttle

    • 鼠标不断点击触发,mousedown(单位时间内只触发一次)
    • 监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断
```// 防抖
function debounce(fn, delay = 300) {
  //默认300毫秒
  let timer;
  return function () {
    const args = arguments;
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      fn.apply(this, args); // 改变this指向为调用debounce所指的对象
    }, delay);
  };
}

window.addEventListener(
  "scroll",
  debounce(() => {
    console.log(111);
  }, 1000)
);

// 节流
// 设置一个标志
function throttle(fn, delay) {
  let flag = true;
  return () => {
    if (!flag) return;
    flag = false;
    timer = setTimeout(() => {
      fn();
      flag = true;
    }, delay);
  };
}

window.addEventListener(
  "scroll",
  throttle(() => {
    console.log(111);
  }, 1000)
)

摘自: juejin.cn/post/684490…

11 深拷贝 浅拷贝

  • 浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象

  • 深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象

深拷贝:

  • 递归复制所有属性
  • 判断是否是object,如果是则递归复制,否则简单复制
  • 实现:Json.paesr ; Json.Stringify() 浅拷贝;
  • object.assign()对象
  • 扩展运算符
  • Array.concat();Array.slice()

链接:juejin.cn/post/684490…

12 原型与原型链

摘自 juejin.cn/post/693449…

13 作用域与作用域链

摘自 juejin.cn/post/684490…

14 前端性能优化指南

摘自 juejin.cn/post/684490…

15 React常见面试题

摘自 juejin.cn/post/698103…

16高频面试题

  1. CSS 实现水平垂直居中

  2. flex的属性

  3. CSS transition的实现效果和有哪些属性

  4. CSS 实现沿Y轴旋转360度

  5. JS 基本数据类型有哪些 用什么判断 引用类型和基本类型的区别
    什么是栈?什么是堆? juejin.cn/post/684490…

  6. 数组怎么判断 juejin.cn/post/684490…

  7. 手写 翻转字符串

  8. 手写 Sum(1,2,3)的累加(argument)(我以为是柯里化,面试官笑了一下,脑筋不要这么死嘛)

  9. 箭头函数和普通函数的区别(上题忘记了argument,面试官特意问这个问题提醒我,奈何基础太差救不起来了...泪目)juejin.cn/post/684490…

  10. 数组去重的方法 juejin.cn/post/684490…

  11. 图片懒加载

  12. 跨域产生的原因,同源策略是什么 juejin.cn/post/684490…

  13. 说说你了解的解决办法(只说了JSONP和CORS)

  14. Cookie、sessionStorage、localStorage的区别 juejin.cn/post/684490…

  15. get 和 post 的区别 (只说了传参方式和功能不同,面试官问还有吗 其他的不知道了...)

  16. 问了一下项目,react

  17. 对ES6的了解 (Promise果真逃不了....)

  18. let var const的区别

  19. 知道Promise嘛?聊聊对Promise的理解?(说了一下Promise对象代表一个异步操作,有三种状态,状态转变为单向...)

那它是为了解决什么问题的?(emmm当异步返回值又需要等待另一个异步就会嵌套回调,Promise可以解决这个回调地狱问题)

那它是如何解决回调地狱的?(Promise对象内部是同步的,内部得到内部值后进行调用.then的异步操作,可以一直.then .then ...)

好,你说可以一直.then .then ...那它是如何实现一直.then 的?(emmm... 这个.then链式调用就是...额这个...)

Promise有哪些方法 all和race区别是什么

具体说一下 .catch() 和 reject (...我人麻了...)