2023年前端面试高频八股文(一)

△ 338 次 手写题库

△ 200 次 Vue 中双向数据绑定的实现原理是怎样的?

Vue2

  • new Vue() 首先执行初始化,对 data 执行响应化处理,这个过程发生 Observe 中
  • 同时对模板执行编译,找到其中动态绑定的数据,从 data 中获取并初始化视图,这个过程发生在 Compile 中
  • 同时定义⼀个更新函数和 Watcher,将来对应数据变化时 Watcher 会调用更新函数
  • 由于 data 的某个 key 在⼀个视图中可能出现多次,所以每个 key 都需要⼀个管家 Dep 来管理多个 Watcher
  • 将来 data 中数据⼀旦发生变化,会首先找到对应的 Dep,通知所有 Watcher 执行更新函数

点击显示代码👇

js 复制代码
Object.defineProperty(obj, key, {
  enumerable: true,
  configurable: true,
  get: function reactiveGetter() {
    // ...
    if (Dep.target) {
      // 收集依赖
      dep.depend();
    }
    return value;
  },
  set: function reactiveSetter(newVal) {
    // ...
    // 通知视图更新
    dep.notify();
  },
});

Vue3

改用 ES6 的 Proxy 解决以前使用 Object.defineProperty 所存在的一些问题

  • 对象新增属性为什么不更新 - $set
  • 数组变异 - 手动 observer,重写数组的方法

△ 188 次 什么是闭包,什么是立即执行函数,它的作用是什么?简单说一下闭包的使用场景

闭包指可以从内部函数访问外部函数的作用域

立即执行函数是一个在定义时就会立即执行的 JavaScript 函数

立即执行函数的作用

  • 不必为函数命名,避免了污染全局变量
  • IIFE 内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量

闭包的使用场景

  • 节流防抖、柯里化
  • 立即执行函数

△ 186 次 简述浏览器的渲染过程,重绘和重排在渲染过程中的哪一部分?

  • 浏览器解析 URL 获取协议,主机,端口, path
  • 浏览器获取主机 IP 地址
  • 建立 TCP 连接,然后发送 HTTP 请求
  • 服务器将响应报文通过 TCP 连接发送回浏览器,浏览器接收 HTTP 响应,根据资源类型决定如何处理
  • 根据 HTML 解析出 DOM 树
  • 根据 CSS 解析生成 CSS 规则树
  • 结合 DOM 树和 CSS 规则树,生成渲染树
  • 根据渲染树计算每一个节点的信息
  • 根据计算好的信息绘制页面

重绘和重排

回流时,渲染流程会重新走一遍。重绘时,会重新计算样式,跳过中间步骤直接生成绘制列表。可见,重绘不一定导致回流,但回流一定发生了重绘。

△ 182 次 简述 diff 算法的实现机制和使用场景

diff 同层对比

新旧虚拟 DOM 对比的时候,diff 算法比较只会在同层级进行,不会跨层级比较。所以 diff 算法是:深度优先算法、时间复杂度:O(n)

diff 对比流程

当数据改变时,会触发 setter,并且通过 Dep.notify 去通知所有订阅者 Watcher,订阅者们就会调用 patch 方法,给真实 DOM 打补丁,更新相应的视图

patch 方法

patch 对比当前同层的虚拟节点是否为同一种类型的标签:

  • 是:继续执行 patchVnode 方法进行深层比对
  • 不是:没必要比对了,直接整个节点替换成新虚拟节点

sameVnode 会比较 key 值、标签名、是否为注释节点、是否定义了 data 和当标签为 input 时,type 必须相同

patchVnode 方法

主要判断:

  • 如果 newVnode 和 oldVnode 是同一个对象,则 return
  • 如果 newVnode 和 oldVnode 是文本节点,且文本不同,则将 el 中文本更新为 newVnode 的文本
  • 如果 newVnode 和 oldVnode 都有子节点,且不同,则对比子节点
  • 如果 oldVnode 有子节点而 newVnode 没有,则删除 el 的子节点
  • 如果 oldVnode 没有子节点而 newVnode 有,则将 newVnode 的子节点真实化之后添加到 el

updateChildren 方法

子节点不完全一致,则调用 updateChildren,while 循环主要处理了以下五种情景:

  • oldStart 和 newStart 使用 sameVnode 方法进行比较,sameVnode(oldStart, newStart)
  • oldStart 和 newEnd 使用 sameVnode 方法进行比较,sameVnode(oldStart, newEnd)
  • oldEnd 和 newStart 使用 sameVnode 方法进行比较,sameVnode(oldEnd, newStart)
  • oldEnd 和 newEnd 使用 sameVnode 方法进行比较,sameVnode(oldEnd, newEnd)
  • 如果以上逻辑都匹配不到,再把所有旧子节点的 key 做一个映射到旧节点下标的 key -> index 表,然后用新 vnode 的 key 去找出在旧节点中可以复用的位置

Vue3.0 diff

  • PatchFlag。Vue3.0 对于不参与更新的元素,做静态标记并提示,只会被创建一次,在渲染时直接复用
  • cacheHandlers。事件侦听器缓存
  • 最长递增子序列

△ 178 次 简述 Javascript 中的防抖与节流的原理并尝试实现

点击显示代码👇

js 复制代码
// 防抖
function debounce(fn, wait) {
  let timeout = null;
  return function () {
    let context = this;
    const args = arguments;
    if (timeout) clearTimeout(timeout);
    timeout = setTimeout(() => {
      fn.apply(context, args);
    }, wait);
  };
}

// 节流
function throttle(fn, wait) {
  let pre = new Date();
  return function () {
    let context = this;
    let args = arguments;
    let now = new Date();
    if (now - pre >= wait) {
      fn.apply(context, args);
      pre = now;
    }
  };
}

△ 172 次 promise 有哪些状态?简述 promise.all 的实现原理

Promise 状态

  • 待定(pending):初始状态,既没有被兑现,也没有被拒绝。
  • 已兑现(fulfilled):意味着操作成功完成。
  • 已拒绝(rejected):意味着操作失败。

promise.all 的实现原理

点击显示代码👇

js 复制代码
function myPromiseAll(promises) {
  return new Promise(function (resolve, reject) {
    if (!isArray(promises)) {
      return reject(new TypeError("arguments must be an array"));
    }
    var resolvedCounter = 0;
    var promiseNum = promises.length;
    var resolvedValues = new Array(promiseNum);
    for (var i = 0; i < promiseNum; i++) {
      (function (i) {
        Promise.resolve(promises[i]).then(
          function (value) {
            resolvedCounter++;
            resolvedValues[i] = value;
            if (resolvedCounter === promiseNum) {
              return resolve(resolvedValues);
            }
          },
          function (reason) {
            return reject(reason);
          }
        );
      })(i);
    }
  });
}

△ 166 次 简述 CSS 盒模型

在 CSS 中,盒子模型可以分成:

  • W3C 标准盒子模型 box-sizing: content-box
  • IE 怪异盒子模型 box-sizing: border-box

标准盒子模型

  • 盒子总宽度 = width + padding + border + margin
  • 盒子总高度 = height + padding + border + margin

width/height 只是内容高度,不包含 padding 和 border 值

IE 怪异盒子模型

  • 盒子总宽度 = width + margin;
  • 盒子总高度 = height + margin;

width/height 包含了 padding 和 border 值

△ 142 次 简述 Javascript 原型以及原型链

原型

实例的 proto 指向构造函数的 prototype

原型链

  • constructor 指向构造函数,每个对象的 proto 指向创建它的构造函数的 prototype,⽽构造函数的 prototype 也有 proto 指向他的⽗辈或者是 Object,当查找⼀个对象中不存在的属性时,会去它的 proto、proto 中的 proto 中进⾏寻找,直到找到或者是 null 为⽌
  • instanceof 判断对象的 proto 和构造函数的 prototype 是不是同⼀个地址
  • Object.setPrototypeOf 改变对象的 proto

△ 138 次 简述什么是 XSS 攻击以及 CSRF 攻击?

XSS 跨站脚本攻击

  1. 可能是写⼀个死循环、获取 cookie 登录
  2. 监听⽤户⾏为
  3. 修改 DOM 伪造登录表单
  4. 页⾯⽣成浮窗⼴告

XSS 防范

  • 对输⼊转码过滤

  • 利⽤ CSP 浏览器内容安全策略,核⼼就是服务器决定浏览器加载哪些资源,功能:

    1. 限制其他域下的资源加载
    2. 禁⽌向其它域提交数据
    3. 提供上报机制
  • HttpOnly HttpOnly 类型的 cookie 阻⽌ JS 对其的访问(标记或授权对话) 阻⽌ XSS 攻击:服务器对脚本进⾏过滤或转码,利⽤ CSP 策略,使⽤ HttpOnly;

CSRF-跨站伪造请求(钓鱼)

攻击者诱导受害者进⼊第三⽅⽹站,在第三⽅⽹站中,向被攻击⽹站发送跨站请求。利⽤受害者在被攻击⽹站已经 获取的注册凭证(⽐如 cookie) ,绕过后台的⽤户验证,因此可以冒充⽤户对被攻击的⽹站执⾏某项操作。

CSRF 防范

  • SameSite SameSite 可以设置为三个值,Strict、Lax 和 None。 a. 在 Strict 模式下,浏览器完全禁⽌第三⽅请求携带 Cookie。⽐如请求 sanyuan.com ⽹站只能在 sanyuan.com 域名当 中请求才能携带 Cookie,在其他⽹站请求都不能。 b. 在 Lax 模式,宽松⼀点,但是只能在 get ⽅法提交表单况或者 a 标签发送 get 请求的情况下可以携带 Cookie,其 他情况均不能。 c. 在 None 模式下,也就是默认模式,请求会⾃动携带上 Cookie。

  • 验证来源站点

    请求头中的 origin 和 referer origin 只包含域名信息,referer 包含具体的 URL 路径。

  • CSRF Token

    利⽤ token(后端⽣成的⼀个唯⼀登陆态,传给前端保存)每次前端请求都会带 token,后端检验通过才同意请求。 敏感操作需要确认 敏感信息的 cookie 只能有较短的⽣命周期

  • 安全框架

    如 Spring Security。

△ 134 次 CSS 的选择器优先级是怎样?

选择器 格式 优先级权重
id 选择器 #id 100
类选择器 .classname 10
属性选择器 a[ref = "eee"] 10
伪类选择器 li:last-child 10
标签选择器 div 1
伪元素选择器 li:after 1
相邻兄弟选择器 h1 + p 0
⼦选择器 ul > li 0
后代选择器 li a 0
通配符选择器 * 0
相关推荐
江湖十年3 分钟前
万字长文:彻底掌握 Go 1.23 中的迭代器——原理篇
后端·面试·go
excel5 分钟前
前端必备:从能力检测到 UA-CH,浏览器客户端检测的完整指南
前端
前端小巷子12 分钟前
Vue 3全面提速剖析
前端·vue.js·面试
悟空聊架构18 分钟前
我的网站被攻击了,被干掉了 120G 流量,还在持续攻击中...
java·前端·架构
CodeSheep20 分钟前
国内 IT 公司时薪排行榜。
前端·后端·程序员
尖椒土豆sss24 分钟前
踩坑vue项目中使用 iframe 嵌套子系统无法登录,不报错问题!
前端·vue.js
遗悲风24 分钟前
html二次作业
前端·html
江城开朗的豌豆28 分钟前
React输入框优化:如何精准获取用户输入完成后的最终值?
前端·javascript·全栈
CF14年老兵28 分钟前
从卡顿到飞驰:我是如何用WebAssembly引爆React性能的
前端·react.js·trae
画月的亮31 分钟前
前端处理导出PDF。Vue导出pdf
前端·vue.js·pdf