关于前端:一周一个大厂复盘一下Taptap的面经发现不足逐一击破

35次阅读

共计 4714 个字符,预计需要花费 12 分钟才能阅读完成。

前言

大家好,我是林三心,用最通俗易懂的话讲最难的知识点 是我的座右铭,根底是进阶的前提 是我的初心

一周一个大厂 是我新出的一个系列文章,大略的流程是这样的:

  • 我会收集一些大厂的面经,并试着去答复
  • 如果全都会则期待下一周从新一轮
  • 如果有不会的,则记录下来,并去克服它们,写成文章,而后下一轮

这个系列的目标就是:逼本人学习,写文章坚固新常识,且温习旧常识

Taptap

明天是 一周一个大厂 的第一期,明天咱们来复盘一下Taptap 的面经,发现有余,并逐个击破他们吧!

一面

1、换肤都做过什么解决,有没有解决过可能扭转尺寸的换肤

我别离在在 微信小程序 PC 管理系统 中做过换肤

  • 小程序:咱们公司做的是一款游戏类的小程序,这款小程序中波及到换肤的中央是浏览故事情节的弹出抽屉,需要是通过用户点击按钮,扭转三种皮肤,并且同时扭转浏览文本的色彩。我的解决方案是,利用 Map 存储三种皮肤信息,点击按钮后会匹配 Map 中对应的皮肤,进行抽屉背景图片的替换,并通过正则的形式,批改浏览文本 HTML 代码,替换 style 里的 color 属性,达到换肤成果
  • PC 管理系统:咱们公司的一款后盾管理系统,做了 黑夜模式 白天模式 的切换性能,跟产品确定主题色之后,开始编程工作。因为咱们的零碎是应用 antd 组件库进行编写的,所以须要引入 antd 相应的主题文件,并封装相应的 切换主题 hook ,同时也要贮存主题标识到 localStorage 中,确保刷新后主题还原。接着就是封装一个 AppDarkModeToggle 的一个切换组件,切换后触发事件,扭转 html data-dark 属性,通过属性选择器,触发底下标签的款式切换,同时扭转 Header,Sider,Footer 等布局组件的 背景色彩、字体色彩 等的切换

2、i18n 在团队外部都做了哪些实际?

我的项目施行

i18n 的意思是 让产品无需做大的扭转就可能适应不同语言和地区的须要 。在我的我的项目中也做过 i18n ,咱们做的是 官网 管理系统 国际化语言切换 ,切换的是 中文 英文 两种语言,我过后的步骤是

  • 1、依据设计稿确定 中文 英文 的文本状况
  • 2、整顿成两个文件夹 en zh ,别离寄存对应语言的材料
  • 3、确定一下材料的模式是对象的键值对模式
  • 4、通过 vite import.meta.globEager 办法,将两种材料整顿成 i18n 插件 所需的格局(不同插件所需格局不同)
  • 5、在我的项目初始化时,初始化 i18n 插件
  • 6、封装对应的切换语言组件—— AppLocalePicker ,用来切换主题,同时扭转 html 标签的 lang 属性
  • 7、同时做好 语言标识 的初始化,防止 刷新后状态失落

插件抉择

我会抉择一些应用起来比拟不便的插件,来实现 i18n

  • Vue:Vue 我抉择的插件是 vue-i18n
  • React:Reacr 我抉择的插件是 i18next

3、Webpack 迁徙 Vite 遇到了哪些问题

  • 1、环境变量须要 Vite_ 前缀
  • 2、获取环境变量形式为 import.meta
  • 3、Vue 中应用 tsx 时报错: React is not defined

    // vite.config.ts
    esbuild: {
      jsxFactory: 'h',
      jsxFragment: 'Fragment',
      jsxInject: 'import {h} from"vue";',
    },
  • 4、主题插件 vite-plugin-theme
  • 5、windicss 的插件 vite-plugin-windicss
  • 6、尽量不必 commonjs ,应用 es module

4、CI/CD 做过哪些实际?

  • CI 代表了 继续集成 ,我了解的意思就是,咱们每天都会编写代码,并且提交到骨干分支上,天天如此,是一个重复性很高的操作, 继续集成 我了解就是会以最快的速度帮你把代码提交到主分支上,这样的益处就是,当开发人员数量多的时候,这样疾速的集成,有利于缩小开发人员代码之间的抵触
  • CD 代表了 继续部署 ,我了解就是既然有 继续集成 代码的话,而代码的集成必定是为了最初的公布部署,所以 继续部署 就是在主动集成代码后,主动部署到环境上,节约了很多人力

已经在之前的公司里参加过 CI/CD 的工作流程,并应用过,然而没有去深刻地实现过,过后公司是应用 Jenkins

5、鉴权有理解过吗?jwt 如何实现踢人,session 和 jwt 鉴权的区别?

session 鉴权

session 鉴权 是须要服务端存储的

  • 1、用户登录
  • 2、服务端接管到登录申请,生成相应的用户标识,存在服务端
  • 3、服务端将标识传给前端,这个标识存在 Cookie 中,并存在浏览器
  • 4、前端接下来每次申请都会带着这个 Cookie 去申请
  • 5、服务端接管到标识,拿标识去数据库里匹配,匹配到则承受,匹配不到则不承受
  • 6、用户登记时,前后端都会销毁这个标识

jwt 鉴权

jwt 鉴权 是不须要服务端存储的

  • 1、用户登录
  • 2、服务端接管到登录申请,依据用户信息,生成一个 token 给前端
  • 3、前端接管到 token ,存在了 浏览器本地缓存 中(例如 LocalStorage
  • 4、接下来每次申请,都需将 token 带在 申请头
  • 5、服务端解析前端传来的 token ,无效则承受,有效则返回 401
  • 6、用户登记时,只须要前端销毁这个 token

jwt 踢人

我了解的 jwt 踢人 ,就是后端管制某个人的 token 有效,我能想到四种办法

  • 1、服务端生成 token 的同时,生成一段 标识 1 ,把 标识 1 + token 发给前端,当我想踢掉某个人时,后端就生成一个新的 标识 2 ,并批改此用户对应的 token 为 标识 2 + token ,那么下次此用户下次带着 标识 1 + token 拜访时,便会测验不通过。这种办法须要用到服务端存储,违反了 jwt 鉴权 的初衷
  • 2、设置两个 token,一个 access_token 一个 refresh_token ,前者过期工夫较短,为 1 小时,后者过期工夫较长,为一个月。将 refresh_token 存在后端数据库(例如 redis), access_token 发给前端,前端拿着 access_token 申请时,都要判断 redis 中 refresh_token 过期了没,没过期的话就通过,或者 access_token 过期了,只有 refresh_token 还没过期,就刷新 access_token 返回给前端。那么想要踢某人下线,就好办了,间接把 refresh_token 从 redis 中革除就行。毛病跟第 1 点一样
  • 3、黑名单模式。就是把须要踢的用户的 token 放在一个数组里,此用户拜访时,遍历数组看有没有这个人,有的话就踢下线
  • 4、另外一种踢人模式是,在咱们公司的游戏业务中,踢人下线是应用了 Websocket 的技术,实时将人踢出房间,不波及 token

6、TCP 三次握手 http1.0 http1.1 http2 都有哪些区别?

HTTP 始终是我的不足之处,记录下来,记录下来

7、https,为什么能够避免中间人攻打?

举荐我写的一篇文章我画了 13 张图,用最通俗易懂的话讲 HTTPS,拿下!

8、冒泡排序

均匀工夫复杂度

O(n^2)

思路

数组中有 n 个数,比拟每相邻两个数,如果前者大于后者,就把两个数替换地位;这样一来,第一轮就能够选出一个最大的数放在最初面;那么通过 n-1(数组的 length – 1)轮,就实现了所有数的排序。

实现

 // 从大到小排序
    var array=[10,20,9,8,79,65,100];
    // 比拟轮数
    for (var i=0;i<array.length-1;i++){
        // 每轮比拟次数,次数 = 长度 -1- 此时的轮数
        for (var j=0;j<array.length-1-i;j++) {if (array[j] > array[j + 1]) {var temp = array[i];
                array[j] = array[j + 1];
                array[j + 1] = temp;
            } //end if
        }//end for 次数
    } //end for 轮数
    console.log(array);

二面

1、给你一个曾经升序排列的数组,给一个数字,找一下这个数字在这个数组里呈现了几次

思路

既然是升序排列过了,那阐明这个数字如果屡次呈现。那必定是紧挨着的,所以不须要遍历残缺个数组,只有以遇到这个数字开始,来到这个数字为完结,这段时间统计完就能够跳出遍历了,不须要做前面的无用功(这是我仅能想到的优化点)

实现

const arr = [1, 2, 3, 4, 5, 5, 6, 6, 7]

const computed = (arr: number[], num: number): number => {
  let flag = false
  let sum = 0
  for (let item of arr) {if (item === num) {
      sum++
      flag = true
      continue
    }
    if (item !== num && flag) break
  }

  return sum
}

console.log(computed(arr, 5))

2、洗牌算法,如何验证这个洗牌算法能够把牌洗得足够乱

1、随机索引 I

  • 1、创立一个空数组
  • 2、生成一个 0 —— length - 1 的随机索引,并将此随机索引对应元素放到新数组里
  • 3、删除原数组中此索引对应元素,原数组 length 更新
  • 4、反复 2、3,直到原数组 length === 0
  • 5、返回新数组

    const shuffle = (arr: number[]) => {if (!arr.length) return []
    let random: number
    let res: number[] = []
    while (arr.length) {random = Math.floor(Math.random() * arr.length)
      res.push(arr[random])
      arr.splice(random, 1)
    }
    return res
    }

2、随机索引 II

  • 1、选取数组 (长度 n) 中最初一个元素 (arr[length-1]) ,将其与 n 个元素中的任意一个替换,此时最初一个元素曾经确定
  • 2、选取倒数第二个元素 (arr[length-2]) ,将其与 n - 1 个元素中的任意一个替换
  • 3、反复第 1 2 步,直到剩下 1 个元素为止
const shuffle = (arr: number[]) => {if (!arr.length) return []
  let index = arr.length - 1
  let random: number
  while (index) {random = Math.floor(Math.random() * index--)
    // 或者
    // random = (Math.random() * index--) >>> 0
    const temp = arr[index]
    arr[index] = arr[random]
    arr[random] = temp
    // 这样也行,然而我的 eslint 不容许哈哈
    // [arr[lastIndex], arr[random]] = [arr[random], arr[lastIndex]]
  }

  return arr
}

3、sort 办法

const shuffle = (arr: number[]) => {return arr.sort(() => 0.5 - Math.random())
}

3、node stream 去取一个超大数据量的日志,因为内存限度每次只能取一部分,当初心愿在全副日志中随机取一万条,如何做?

这一道题不会。。记录下来,记录下来

4、介绍一下我的项目 有哪些是由你主导提出的计划做的事件

主导过两、三个我的项目:

  • 我的项目 A:小程序
  • 我的项目 B:官网
  • 我的项目 C:后盾管理系统

有余记录

  • TCP 三次握手 http1.0 http1.1 http2 都有哪些区别?
  • CI/CD 的实践经验有余
  • node stream 的应用

结语

我是林三心,一个热心的前端菜鸟程序员。如果你上进,喜爱前端,想学习前端,那咱们能够交朋友,一起摸鱼哈哈,摸鱼群

题目摘取

此次面经题目摘取自时隔一年半,我,一个低微的前端菜鸡,又来写面经了

正文完
 0