文章目录

1. 写在前面

  有时候一些其他领域的小伙伴,会私信问一些非博主领域相关触及知识盲区的问题,什么C++,C#,大前端…

其中有很多朋友问面试相关的,我之前的文章内有一篇关于Python领域面经汇总的置顶文章,那篇文章在我有空的时候,有价值的问题也会持续更新收录进去,感兴趣的可以去阅读:

极具参考价值的Python面试题!从创业公司到一线大厂的真实面经汇总(持续更新)

最近有几位朋友问前端的面试题目,说实话,我很难从专业的角度去给出总结,但是既然大家有需要,我还是在周末之余通过咨询相关领域的朋友跟目前比较主流的一些问题进行了一个汇总,于是有了这么一篇文章,希望它能够帮到你

【持续更新】汇总了一份前端领域必看面试题-LMLPHP

2. 前端面试汇总

2.0.1. 如何提⾼webpack的打包速度

  • 优化Loader
      对于 Loader 来说,影响打包效率首当其冲必属 Babel 了。因为 Babel 会将代码转为字符串生成 AST,然后对 AST 继续进行转变最后再生成新的代码,项目越大,转换代码越多,效率就越低。当然了,这是可以优化的

首先优化Loader的文件搜索范围:

module.exports = {
  module: {
    rules: [
      {
        // js 文件才使用 babel
        test: /\.js$/,
        loader: 'babel-loader',
        // 只在 src 文件夹下查找
        include: [resolve('src')],
        // 不会去查找的路径
        exclude: /node_modules/
      }
    ]
  }
}

对于 Babel 来说,希望只作用在 JS 代码上的,然后 node_modules 中使用的代码都是编译过的,所以完全没有必要再去处理一遍

当然这样做还不够,还可以将 Babel 编译过的文件缓存起来,下次只需要编译更改过的代码文件即可,这样可以大幅度加快打包时间

2.0.2. 数组去重

  遍历旧数组,然后拿着旧数组元素去查询新数组,如果该元素在新数组里面没有出现过,我们就添加,否则不添加。先封装一个函数,unique:

function unique(arr){
var newArr =\[]
for(var i =0; i< arr.length; i++){
if (newArr.indexOf(arr\[i] === -1){
newArr.push(arr\[i])
}
}
return newArr
}
var demo = unique(\[])
console.log(demo)

2.0.3. 前端有几种缓存方式?

  • sessionStorage
    但当页面关闭后,sessionStorage 中的数据就会被清空。 indexdb、 50mb 允许储存大量数据,提供查找接口,支持异步操作,还能建立索引。indexDB缺点是:不支持DO操作;不能跨域
  • localStorage
    5M大小只能存储字符串格式的数据,所以最好在每次存储时把数据转换成json格式, 取出的时候再转换回来 生命周期是永久的, 除非主动删除数据,否则数据永远不会消失
  • cookiec
    当在客户端的浏览器上设置Cookie时,它可以持续数天,数月甚至数年。这样可以轻松保存用户首选项和访问信息 不需要任何服务器资源,并存储在用户的计算机上,因此不会给服务器带来额外的负担。 确实非常小,它的大小限制为4KB左右,不能储存大数据且不易读取

2.0.4. nextTick描述一下?

2.0.5. Webpack层面的优化?

2.0.6. 代码层面的优化?

2.0.7. Web 技术的优化?

2.0.8. diff算法的优化策略?

四种命中查找,四个指针

2.0.9. 事件循环?它在JS中作用?

2.1.0. 浏览器缓存及作用?

2.1.1. Web Workers作用?

2.1.2. 浏览器垃圾回收机制?

2.1.3. 虚拟DOM实现原理?

2.1.4.

3. CSS相关汇总

3.0.1. CSS中的层叠顺序是如何工作的?

3.0.2. CSS中的伪类和伪元素的区别?示例?

/* 伪类示例 */
a:hover {
  color: red;
}

/* 伪元素示例 */
p::before {
  content: "前缀";
}

3.0.3. v-if和v-for哪个优先级更高

  • cookiec
    当在客户端的浏览器上设置Cookie时,它可以持续数天,数月甚至数年。这样可以轻松保存用户首选项和访问信息 不需要任何服务器资源,并存储在用户的计算机上,因此不会给服务器带来额外的负担。 确实非常小,它的大小限制为4KB左右,不能储存大数据且不易读取

3.0.4. CSS中的BFC它的作用是什么?

3.0.5. CSS中的flexbox布局是什么,它有什么优势?

3.0.6. CSS的盒模型是什么,描述一下?

3.0.7. 描述一下CSS中的选择器及其优先级?

4. Vue相关汇总

4.0.1. v-if和v-for哪个优先级更高?

  在vue2中,v-for的优先级是高于v-if,把它们放在一起,输出的渲染函数中可以看出会先执行循环再判断条件,哪怕我们只渲染列表中一小部分元素,也得在每次重渲染的时候遍历整个列表,这会比较浪费;另外需要注意的是在vue3中则完全相反,v-if的优先级高于v-for,所以v-if执行时,它调用的变量还不存在,就会导致异常

4.0.2. 3.0特性描述一下?

  • 监测机制的改变
    3.0 将带来基于代理 Proxy 的 observer 实现,提供全语言覆盖的反应性跟踪。这消除了 Vue 2 当中基于 Object.defineProperty 的实现所存在的很多限制:(只能监测属性,不能监测对象、检测属性的添加和删除、检测数组索引和长度的变更、支持 Map、Set、WeakMap 和 WeakSet)
  • 模板
    模板方面没有大的变更,只改了作用域插槽,2.x 的机制导致作用域插槽变了,父组件会重新渲染,而 3.0 把作用域插槽改成了函数的方式,这样只会影响子组件的重新渲染,提升了渲染的性能。
    同时,对于 render 函数的方面,vue3.0 也会进行一系列更改来方便习惯直接使用 api 来生成 vdom
  • 对象式的组件声明方式
    vue2.x 中的组件是通过声明的方式传入一系列 option,和 TypeScript 的结合需要通过一些装饰器的方式来做,虽然能实现功能,但是比较麻烦。3.0 修改了组件的声明方式,改成了类式的写法,这样使得和 TypeScript 的结合变得很容易。
    此外,vue 的源码也改用了 TypeScript 来写。其实当代码的功能复杂之后,必须有一个静态类型系统来做一些辅助管理。现在 vue3.0 也全面改用 TypeScript 来重写了,更是使得对外暴露的 api 更容易结合 TypeScript。静态类型系统对于复杂代码的维护确实很有必要
  • 其它方面的更改
    (1)支持自定义渲染器,从而使得 weex 可以通过自定义渲染器的方式来扩展,而不是直接 fork 源码来改的方式
    (2)支持 Fragment(多个根节点)和 Protal(在 dom 其他部分渲染组建内容)组件,针对一些特殊的场景做了处理
    (3)基于 treeshaking 优化,提供了更多的内置功能

4.0.3. vue 中使用了哪些设计模式?

  • 工厂模式:虚拟 DOM 根据参数的不同返回基础标签的 Vnode 和组件 Vnode

  • 单例模式:vuex 和 vue-router 的插件注册方法 install 判断如果系统存在实例就直接返回掉

  • 发布-订阅模式 (vue 事件机制)

  • 观察者模式 (响应式数据原理)

  • 装饰模式: (@装饰器的用法)

  • 策略模式:指对象有某个行为,但是在不同的场景中,该行为有不同的实现方案-比如选项的合并策略

4.0.4. 模板编译原理

Vue 的编译过程就是将 template 转化为 render 函数的过程 分为以下三步:

export function compileToFunctions(template) {
  // 我们需要把html字符串变成render函数
  // 1.把html代码转成ast语法树  ast用来描述代码本身形成树结构 不仅可以描述html 也能描述css以及js语法
  // 很多库都运用到了ast 比如 webpack babel eslint等等
  let ast = parse(template);
  // 2.优化静态节点
  // 这个有兴趣的可以去看源码  不影响核心功能就不实现了
  //   if (options.optimize !== false) {
  //     optimize(ast, options);
  //   }

  // 3.通过ast 重新生成代码
  // 我们最后生成的代码需要和render函数一样
  // 类似_c('div',{id:"app"},_c('div',undefined,_v("hello"+_s(name)),_c('span',undefined,_v("world"))))
  // _c代表创建元素 _v代表创建文本 _s代表文Json.stringify--把对象解析成文本
  let code = generate(ast);
  //   使用with语法改变作用域为this  之后调用render函数可以使用call改变this 方便code里面的变量取值
  let renderFn = new Function(`with(this){return ${code}}`);
  return renderFn;
}

4.0.5. 响应式原理区别?

Vue3.x 改用 Proxy 替代 Object.defineProperty。因为 Proxy 可以直接监听对象和数组的变化,并且有多达 13 种拦截方法

import { mutableHandlers } from "./baseHandlers"; // 代理相关逻辑
import { isObject } from "./util"; // 工具方法

export function reactive(target) {
  // 根据不同参数创建不同响应式对象
  return createReactiveObject(target, mutableHandlers);
}
function createReactiveObject(target, baseHandler) {
  if (!isObject(target)) {
    return target;
  }
  const observed = new Proxy(target, baseHandler);
  return observed;
}

const get = createGetter();
const set = createSetter();

function createGetter() {
  return function get(target, key, receiver) {
    // 对获取的值进行放射
    const res = Reflect.get(target, key, receiver);
    console.log("属性获取", key);
    if (isObject(res)) {
      // 如果获取的值是对象类型,则返回当前对象的代理对象
      return reactive(res);
    }
    return res;
  };
}
function createSetter() {
  return function set(target, key, value, receiver) {
    const oldValue = target[key];
    const hadKey = hasOwn(target, key);
    const result = Reflect.set(target, key, value, receiver);
    if (!hadKey) {
      console.log("属性新增", key, value);
    } else if (hasChanged(value, oldValue)) {
      console.log("属性值被修改", key, value);
    }
    return result;
  };
}
export const mutableHandlers = {
  get, // 当获取属性时调用此方法
  set, // 当修改属性时调用此方法
};

4.0.6. 双向数据绑定如何实现的?

4.0.7. 生命周期钩子?执行顺序?

Vue中的生命周期钩子包括beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy和destroyed。它们的执行顺序如下:

4.0.8. 路由如何实现的?

4.0.9. watch和computed区别是什么?

4.1.0. 依赖注入是什么?它的应用场景?

4.1.1. action和mutation的区别?

mutation中的操作是一系列的同步函数,用于修改state中的变量的的状态。当使用vuex时需要通过commit来提交需要操作的内容。mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是实际进行状态更改的地方,并且它会接受 state 作为第一个参数:

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      state.count++      // 变更状态
    }
  }
})

4.1.2. router和route的区别?

router是VueRouter的一个对象,通过Vue.use(VueRouter)和VueRouter构造函数得到一个router的实例对象,这个对象中是一个全局的对象,包含了所有的路由包含了许多关键的对象和属性。
route是一个跳转的路由对象,每一个路由都会有一个route对象,是一个局部的对象,可以获取对应的name,path,params,query

4.1.3. 插槽是什么?具有命名插槽和作用域插槽的示例?

<!-- 父组件 -->
<template>
  <div>
    <slot name="header"></slot>
    <slot :data="data"></slot>
  </div>
</template>

<!-- 子组件 -->
<template>
  <div>
    <slot name="header">默认标题</slot>
    <slot :data="computedData">{{ computedData }}</slot>
  </div>
</template>

4.1.4. 动画系统是如何工作?简单示例?

Vue.js的动画系统通过CSS过渡和动画类实现。通过在元素上添加过渡类或动画类,可以触发相应的过渡效果或动画效果。示例:

<transition name="fade">
  <div v-if="show">显示内容</div>
</transition>

<!-- CSS样式 -->
<style>
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.5s;
}
.fade-enter, .fade-leave-to {
  opacity: 0;
}
</style>

4.1.5. 错误处理机制?如何捕获?

4.1.6. 响应式数组有哪些限制?如何解决?

4.1.7. Composition API与Options API区别?

4.1.8. Suspense是什么?它的作用?

4.1.9. provide和inject作用?请给出示例?

provide和inject用于实现组件之间的依赖注入。通过在父组件中使用provide提供数据,然后在子组件中使用inject注入这些数据。示例:

// 父组件
const Parent = {
  provide: {
    message: 'Hello Spider!'
  },
  // ...
}

// 子组件
const Child = {
  inject: ['message'],
  created() {
    console.log(this.message); // 输出:Hello Spider!
  },
  // ...
}

4.2.0. watchEffect和watch区别?如何使用?

5. React相关汇总

5.0.1. 核心概念是什么?

5.0.2. 生命周期方法?列举一些?

React生命周期方法是在组件不同阶段执行的特定方法。以下是一些常用的React生命周期方法:

5.0.3. React Context?作用?

5.0.4. React Router?作用?

5.0.5. React Hooks?作用?

  好了,到这里又到了跟大家说再见的时候了。创作不易,帮忙点个赞再走吧。你的支持是我创作的动力,希望能带给大家更多优质的文章

11-25 16:04