中级前端面试100问,每日一问,持续更新…

子成君 1.2K 1
温馨提示

问题和答案均收集于网络,部分题目为本人作答,若有错误望指出...

1.url输入到页面显示全过程

其实从输入URL到页面展示在我们眼前所经历的过程其实还是非常复杂的,牵扯到的知识点也是非常的庞杂。其中很多知识都会有专门的学科去研究,所以这里只是简单地概括一下大致流程:

  • 1、输入网址
  • 2、DNS解析
  • 3、建立tcp连接
  • 4、客户端发送HTPP请求
  • 5、服务器处理请求
  • 6、服务器响应请求
  • 7、浏览器展示HTML
  • 8、浏览器发送请求获取其他在HTML中的资源。

2.vuex包括哪些内容

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
有 5 种属性,分别是 state、getter、mutation、action、module

vuex 的 store 是什么?
vuex 就是一个仓库,仓库里放了很多对象。其中 state 就是数据源存放地,对应于一般 vue 对象里面的 datastate 里面存放的数据是响应式的,vue 组件从 store 读取数据,若是 store 中的数据发生改变,依赖这相数据的组件也会发生更新它通过 mapState 把全局的 state 和 getters 映射到当前组件的 computed 计算属性
vuex 的 getter 是什么?
getter 可以对 state 进行计算操作,它就是 store 的计算属性虽然在组件内也可以做计算属性,但是 getters 可以在多给件之间复用如果一个状态只在一个组件内使用,是可以不用 getters
vuex 的 mutation 是什么?
更改Vuex的store中的状态的唯一方法是提交mutation
vuex 的 action 是什么?
action 类似于 muation, 不同在于:action 提交的是 mutation,而不是直接变更状态action 可以包含任意异步操作
vuex 的 module 是什么?
面对复杂的应用程序,当管理的状态比较多时;我们需要将vuex的store对象分割成模块(modules)。

3.vue项目优化

1、v-for 遍历必须为 item 添加 key,且避免同时使用 v-if

  • v-for 遍历必须为 item 添加 key

在列表数据进行遍历渲染时,需要为每一项 item 设置唯一 key 值,方便 Vue.js 内部机制精准找到该条列表数据。当 state 更新时,新的状态值和旧的状态值对比,较快地定位到 diff 。

  • v-for 遍历避免同时使用 v-if

v-for 比 v-if 优先级高,如果每一次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染很小一部分的时候,必要情况下应该替换成 computed 属性。

2、v-if 和 v-show 区分使用场景

v-if 是 真正 的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

v-show就简单得多, 不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 的 display 属性进行切换。

所以,v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show则适用于需要非常频繁切换条件的场景。

3、computed 和 watch 区分使用场景

computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;

watch: 更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;

运用场景:
  • 当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;
  • 当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

4、长列表性能优化

Vue 会通过 Object.defineProperty 对数据进行劫持,来实现视图响应数据的变化,然而有些时候我们的组件就是纯粹的数据展示,不会有任何改变,我们就不需要 Vue 来劫持我们的数据,在大量数据展示的情况下,这能够很明显的减少组件初始化的时间,那如何禁止 Vue 劫持我们的数据呢?可以通过 Object.freeze 方法来冻结一个对象,一旦被冻结的对象就再也不能被修改了。

5、事件的销毁

Vue 组件销毁时,会自动清理它与其它实例的连接,解绑它的全部指令及事件监听器,但是仅限于组件本身的事件。 如果在 js 内使用 addEventListene 等方式是不会自动销毁的,我们需要在组件销毁时手动移除这些事件的监听,以免造成内存泄露

6、图片资源懒加载

对于图片过多的页面,为了加速页面加载速度,所以很多时候我们需要将页面内未出现在可视区域内的图片先不做加载, 等到滚动到可视区域后再去加载。这样对于页面加载性能上会有很大的提升,也提高了用户体验。

7、路由懒加载

Vue 是单页面应用,可能会有很多的路由引入 ,这样使用 webpcak 打包后的文件很大,当进入首页时,加载的资源过多,页面会出现白屏的情况,不利于用户体验。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应的组件,这样就更加高效了。这样会大大提高首屏显示的速度,但是可能其他的页面的速度就会降下来。

路由懒加载:

const Foo = () => import('./Foo.vue')
const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})
8、第三方插件的按需引入

我们在项目中经常会需要引入第三方插件,如果我们直接引入整个插件,会导致项目的体积太大,我们可以借助 babel-plugin-component ,然后可以只引入需要的组件,以达到减小项目体积的目的。

4.权限模块粒度怎样设计的,具体到代码如何控制?

  • 与后端约定需要控制页面的权限列表permissionList(我跟后端开发者约定的格式是object形式的,key值是页面router的name,value是个Boolean值,这样进行权限判断的时候取值方便)
  • 在每个可访问页面的路由定义的时候添加meta属性,并设置requireAuth: true(同时也可以传一些其他你自己需要的配置信息,可以在页面内访问到的哦)
{
  path: '/home',
  name: 'home',
  component: home,
  meta: {
    requireAuth: true
  }
}
  • 侧边菜单栏(或者在顶部,反之就是菜单)前端写好,每一个叶子结点肯定都对应的有一个点击跳转的页面,所以在渲染菜单的时候要对每个菜单节点判断对应的页面是否有权限,如果没有该叶子结点就不展示
  • 在router的钩子函数beforeEach中添加监听,因为每次页面触发路由变化的时候都会触发该钩子函数,然后判断要前往(参数to)的页面是否需要判断权限即meta中的requireAuth字段,如果需要,那么就从vuex中读取权限列表,然后判断需要前往的页面是否有权限,如果没有就跳转无权限页面(如果项目没有这个页面的话就不进行跳转),反之就正常页面切换
router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    // 表示要前往的页面需要权限
    // 添加自己的判断条件
    if (xxx) {
      next({path: '/xxx'})
    } else {
      // 跳转无权限页面
      next({path: '/forbidden'})
    }
  } else {
    next() // 确保一定要调用 next()
  }
})

另外可以参考官方文档关于路由元的讲解

5.公众号开发项目具体说说

一、注册公众号
二、了解公众号管理页面
三、必备开发者工具的使用
1.开发者文档
2.在线接口调试工具
3.web开发者工具
4.公众平台测试账号
四、细读开发者文档
五、开发流程重点解析
1.开发环境准备
2.服务器基本配置
3.存取access_token参数
4.公众号消息管理
5.获取openid以及网页授权(重难点)
(1)先明确为什么需要网页授权?我们的目的是什么?
(2)既然目的是获取用户基本信息,微信不是提供了专门的接口吗?非要网页授权?
微信平台提供了两种方式获取用户的openid
(3)网页授权有哪几种机制?分别是怎样实现?应用于什么场景?
(4)想要进行网页授权,我们需要在公众平台配置什么吗?
原文:https://blog.csdn.net/Abysscarry/article/details/89071469

6.如何部署Nginx,以及如何配置?

详看掘金:https://juejin.im/post/5df43d6df265da33ef668688

7.es6语法用过哪些

const和let,模板字符串,箭头函数(Arrow Functions),函数的参数默认值,扩展运算符,解构赋值,

for...of 和 for...in,ES6中的类,继承以及super()方法

8.基本数据类型

JavaScript 中共有 7 种基本数据类型:UndefinedNullBooleanNumberStringSymbol (new in ES 6) 和新加入的BigInt

剩下的就是引用类型了,统称为 Object 类型。细分的话,有:Object 类型Array 类型Date 类型RegExp 类型Function 类型 等。

9.什么是闭包

函数嵌套函数,里面的函数可以调用外面函数的变量,那它就是一个闭包

function init() {
    var name = "Mozilla"; // name 是一个被 init 创建的局部变量
    function displayName() { // displayName() 是内部函数,一个闭包
        alert(name); // 使用了父函数中声明的变量
    }
    displayName();
}
init();

10.100*100的 canvas 占多少内存?

其实真正的答案是多少我并不清楚,面试过程中面试官也不期待一个准确的答案,而是看你的思考过程。

如果了解过 Canvas 且做过滤镜相关的工作,可能调用过 imageData = ctx.getImageData(sx, sy, sw, sh); 这个 API。我记得这个 API 返回的是一个 ImageData 数组,包含了 sx, sy, sw, sh 表示的矩形的像素数据。

而且这个数组是 Uint8 类型的,且四位表示一个像素。

我在面试的时候只能想起来这些信息。猜想一下,我们在定义颜色的时候就是使用 rgba(r,g,b,a) 四个维度来表示,而且每个像素值就是用十六位 00-ff 表示,即每个维度的范围是 0~255,即 2^8 位,即 1 byte, 也就是 Uint8 能表示的范围。

所以 100 * 100 canvas 占的内存是 100 * 100 * 4 bytes = 40,000 bytes。

详情:https://github.com/xiaoyu2er/blog/issues/15

11.JS 判断两个数组是否相同

(是个坑,双等三等都不行,得排序后转成字符串比较)

JSON.stringify([1,2,3].sort()) === JSON.stringify([3,2,1].sort());  //true
或者
[1,2,3].sort().toString() === [3,2,1].sort().toString();  //true

12.undefined和null区别

JavaScript的最初版本没有包括错误处理机制,发生数据类型不匹配时,往往是自动转换类型或者默默地失败。Brendan Eich觉得,如果null自动转为0,很不容易发现错误。

因此,Brendan Eich又设计了一个undefined。

JavaScript的最初版本是这样区分的:null是一个表示"无"的对象,转为数值时为0;undefined是一个表示"无"的原始值,转为数值时为NaN。

null表示"没有对象",即该处不应该有值。典型用法是:

(1) 作为函数的参数,表示该函数的参数不是对象。

(2) 作为对象原型链的终点。
Object.getPrototypeOf(Object.prototype)
// null

undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。典型用法是:

(1)变量被声明了,但没有赋值时,就等于undefined。

(2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。

(3)对象没有赋值的属性,该属性的值为undefined。

(4)函数没有返回值时,默认返回undefined。

13.MVVM如何实现

明日再答,消化每一道题。

发表评论 取消回复
OwO 图片 链接 代码

  1. 北巷博客
    北巷博客 超级小萌新

    [aru_1]把你站css搬过来了

分享