字节暑期实习前端三面
字节暑期实习前端三面
-
自我介绍
-
介绍项目
-
技术选型怎么考虑的?
-
一般在项目中如何运用TS?
-
编写全局的类型声明文件index.d.ts,声明整个项目中用到的数据类型,通过ts.config.json配置全局生效
-
-
Vue3怎么与TS相结合,用TS做了那些类型声明?
-
接口类型定义,响应式数据类型定义,列表渲染数据定义,全局状态和路由组件的类型定义,增强类型检查和代码提示
-
TS一方面充当了使用文档,另一方面减少了手误导致的拼写错误,提供运行时编译检查,例如在伪数组上调用数组方法,在编译阶段直接提示报错
-
通过内置的ThisType显示指定this指向的内容类型,因为this的指向与调用时函数所在的对象,或者调用的方式相关
-
-
实现TS类型
- StartsWith::判断字符串是否以子串为起始
-
/** * 判断字符串是否以子串为起始 * type Result = StartsWith<"123", "12"> // true */ type StartsWith< S1 extends string, S2 extends string > = S1 extends `${S2}${infer Right}` ? true : false;
- Last:判断数组的最后一个元素的类型
-
// 实现一个通用的 Last<T>,它接受一个数组 T 并返回其最后一个元素。 type Last<T extends any[]> = T extends [...any[], infer P] ? P : undefined; type arr1 = ["a", "b", "c"]; type arr2 = [3, 2, 1]; type tail1 = Last<arr1>; // expected to be 'c' type tail2 = Last<arr2>; // expected to be 1
-
-
TS中的never是什么
-
never表示永远不存在的类型
-
比如一个函数总是抛出错误,而没有返回值
-
或者一个函数内部有死循环,永远不会有返回值,函数的返回值就是never类型
-
-
TS中的keyof是什么,有什么用?
-
keyof获取一个类型的属性名所组成的联合类型,可用于创建类型映射
- 例如
-
type MyCord<T extends keyof any, U> = { [Key in T]: U; }; type Test = MyCord<"name" | "age" | "friends", string>; // Test相当于 // type Result = { // name: string; // age: string; // friends: string; // };
-
-
层级关系题目
-
// 以下数据结构中,id 代表部门编号,name 是部门名称,parentId 是父部门编号,为 0 代表一级部门,现在要求实现一个 convert 方法,把原始 list 转换成树形结构,parentId 为多少就挂载在该 id 的属性 children 数组下,结构如下: // 原始 list 如下 let list = [ { id: 1, name: "部门A", parentId: 0 }, { id: 2, name: "部门B", parentId: 0 }, { id: 3, name: "部门C", parentId: 1 }, { id: 4, name: "部门D", parentId: 1 }, { id: 5, name: "部门E", parentId: 2 }, { id: 6, name: "部门F", parentId: 3 }, { id: 16, name: "部门L", parentId: 3 }, { id: 7, name: "部门G", parentId: 2 }, { id: 8, name: "部门H", parentId: 4 }, ]; const result = convert(list); console.log(result); // 转换后的结果如下 // let result = [ // { // id: 1, // // name: "部门A", // // parentId: 0, // // children: [ // { // id: 3, // // name: "部门C", // // parentId: 1, // // children: [ // { // id: 6, // // name: "部门F", // // parentId: 3, // }, // { // id: 16, // // name: "部门L", // // parentId: 3, // }, // ], // }, // // { // id: 4, // // name: "部门D", // // parentId: 1, // // children: [ // { // id: 8, // // name: "部门H", // // parentId: 4, // }, // ], // }, // ], // }, // ]; function convert(list, id = 0) { let res = []; for (let i = 0; i < list.length; i++) { if (list[i].parentId === id) { res.push(list[i]); list[i].children = convert(list, list[i].id); } } return res; }
-
-
权限控制如何实现的?
-
根据角色加载权限列表,角色与权限相绑定,账号与角色相互绑定
-
状态管理确保切换角色后自动更新视图
-
路由过滤获取可访问路由列表
-
路由拦截防止越权访问
-
添加404页面用于非法访问过渡
-
-
设计一个权限控制的组件,伪代码
-
子组件介绍待处理数据,当前用户唯一标识,以及需要做权限控制的字段
-
子组件通过计算属性过滤,再将过滤后的内容列表渲染出来
-
子组件的数据通过作用域插槽传递到父组件,不推荐使用mixin
-
-
service worker是什么,有什么用?
-
Vue子组件如何向父组件传递数据?
-
emit
-
作用域插槽
-
$parent和$children
-
Vuex
-
PubSub
-
-
用Redis干什么?
-
管理好友关系和群聊关系
-
用于保存本次通信中客户端ID与SocketID的映射关系,用于定位客户端
-
实现未读消息记录
-
暂存好友验证列表
-
-
反问