自我介绍
1. 有参与过脚手架的维护吗?
没有。
2. 是怎么去做 codeReview 的?比较注重哪些点?
主要注重编码规范,健壮性检查,质量保证,统一风格,完善注释。
保证代码的可读性,一致性,提升代码质量。
3. 在做视觉稿管理系统的时候,有什么比较印象深刻的有难度的地方吗?
切换主题的设计:使用less,将不同主题的颜色变量写在不同的样式文件中,使用 less-vars-to-js 将各个文件的颜色变量转为js对象, 使用 less.modifyvars 在点击切换主题时进行变量替换。 在 react 中用 less 动态切换主题样式 使用 css/less 动态更换主题色(换肤功能)
消息中心的设计:
因为负责视觉稿管理系统的后端的整体架构和实现,全面的对于后端有了更深刻的理解,让我在数据库建表,前端技术方面有了更大的进步。考虑到消息中心中有两种消息通知,一种是点对点,因为用户操作而产生的通知,一种是系统给全体用户发送的公告,还需要有已读未读的功能,所以新建了两张表,notify_event 存储单条通知,notify_remind 存储单次通知的关联id,发送者、接收者和是否已读等数据。在通知实现方面,考虑到通知的实时性需求不强,采用了间隔5分钟的轮询的方式实现。此外,上传视觉稿或更新视觉稿时,还会通过钉钉群推送的方式通知到该项目相关成员。
部署遇到的工具冲突的问题:
我在这个项目中主要负责Node后端,使用了TS + Egg框架,为了能够实现接口文档在线化,用到了一个通过 Controller 里的注释自动生成接口文档的工具包:egg-swagger-doc-feat。在开发期间,egg-loader 会自动加载 *.ts 并内存编译。此时运行是没有问题的,但在部署时,会将 ts 构建为 js,发现egg-swagger-doc-feat就会报错,Controller 不存在。
刚开始出现这个问题,我就去网络上找答案,但是发现很少有人出现这个问题,去看issue的时候有找到类似问题的答案,但是发现并不适用于我的情况。于是只能通过源码去寻找,发现这个插件有针对 ts 和 js 做相应的优化,在获取controller的时候,做了一个判断,如果是ts文件,就去获取default, 如果是js则直接获取。
if (path.extname(filepath) === '.ts') {
obj = obj.default;
}
当时我们ts文件是这样写的:
export default class DemandController extends Controller {
}
所以能够获取到,但是当运行 npm run tsc 命令将ts转成js后,exports.default = DemandController; 还是存在default,导致获取不到内容,继而后续报错。
发现问题以后我的第一想法是,考虑如何修改自己的代码,去兼容这个工具包:换成 module.exports 的写法,是否可以呢?结果还是不行,因为这样在ts模式下就获取不到内容了。所以最终我是通过将工具包的源码down下来,把它对ts做特殊处理的这一段代码删掉,在公司内部发了一个二方包,解决了这个问题。
光敏:全面的对于后端有了更深刻的理解,如何设计接口,如何设计字段,比如考虑到xx情况,减少了性能开销,对整个项目进行了分析,面向的对象是谁,架构,做的过程中发现了xx问题,优化。复盘过程中解决了什么
4. Node 的基本原理有了解吗?
Node具有异步I/O,事件驱动,单线程等特点。
异步I/O: 类似于前端中的 Ajax 请求,异步代码会在同步代码执行完成后,等待异步返回结果再执行,在Node中,绝大多数操作都是以异步的方式进行调用,从文件读取到网络请求等,好处是,每个调用无需等待之前的I/O调用结束。而同步I/O需要等待前一个I/O调用结束后才能够开始。
事件驱动:通过事件队列,回调函数队列完成任务调度。
单线程:Node中js代码的执行是单线程的。无需像多线程语言处理状态同步问题,也省去了切换线程上下文带来的性能开销。缺点是无法利用多核cpu,错误会引起整个应用的退出,健壮性较差。大量计算会占用CPU导致无法调用异步I/O。
5. Node 的DNS模块,HTTP模块有了解吗?I/O事件模型?
dns和http不了解,I/O 同上。
6. 体现设计能力的一些点?架构上,或某一个功能的设计上?扩展性,稳定性,鲁棒性?
业务场景,用户体验,
业务项目策略中心中,包括标签中心,模型中心,任务中心,其中一个任务对应多个标签和一个模型,用户可以在任务中心中新建、编辑标签和模型,所以在前端模块设计的时候,就将标签和模型的新建页面提取成两个组件。复用在标签、模型、任务中心中。
鲁棒性方面,使用了lodash、解构默认值,try-catch 等方式,来减少读取变量出现的错误;通过例如点击提交按钮后及时将按钮置为loading等方式,来防止用户多次点击。
7. 怎么去做到了支撑快节奏的开发需求?比如说因为设计的比较好,效率比较高?
选择了TS作为开发语言,帮助前端开发者尽快的推断变量类型,提升代码可读性。
8. TS 是你引入的吗?当时是怎么考虑的,做了什么调研?
- TypeScript提供了一种编译阶段的类型系统,在代码提示,错误检测,代码生成及格式化方面答复提高开发效率。
- 丰富的类型,能够帮助开发者尽快推断变量,参数,返回值的类型,提升代码可读性,减少依赖逻辑代码的阅读,将注意力更多的放在功能的具体实现上。
9. 使用TS的话,会对后端获取到的数据类型进行转化吗?还是只是用了interface做了一个类型的标明?
没有做类型转化,做了类型标明。
10. 之前写过Java吗?蓝桥杯。
写过。
11. Java 的面向对象?
封装、继承、多态。
java中对类的属性进行了封装,分为公有和私有。目的是为了保护信息。继承是指子类可以通过继承来获得父类的所有特征和行为。多态是指父类中拥有的属性和行为,在子类继承后可以有不同的表现形式。子类可以在父类的基础上新增属性或行为,或者对于父类的行为进行重载或重写。
12. JS是否是一个面向对象的语言?
类。Object。protoType。
js是基于原型的(prototype),我们能接触到的都是对象。我们也可以通过构造函数,call,apply,bind等方式实现封装,继承,多态。
13. React Hooks 配合 TS 用,React.FC 用过吗?
React.FC是函数式组件,是在TypeScript使用的一个泛型。
14. React 配合 TS 用到 泛型?
泛型就是将所操作的数据类型指定为一个参数,这个参数可以用于类,接口和方法的创建中。
因为ts不建议使用any,不能保证类型安全,调试时缺乏完整的信息,当我们有可重用的组件时,可以使用泛型,它可以支持当前数据类型,也可以支持未来的数据类型,扩展灵活,能够保证类型安全。
15. setState时,一个父组件有两个子组件,父子组件的componentShouldUpdate,和 componentDidUpdate 这两个生命周期的执行顺序是怎样的?
先进行父组件的componentShouldUpdate,两个子组件的componentShouldUpdate,再进行两个子组件的componentDidUpdate,再进行父组件的 componentDidUpdate。
16. PureComponent 是做什么的?
表示一个纯组件,他其实是在componentShouldUpdate时帮助我们对state和props进行了一个浅比较,它可以优化程序,减少渲染次数,提高性能。
17. 如果传给 PureComponent 的是个对象呢?它会深比较还是浅比较?
浅比较,比较的是地址。
18. 为什么是浅比较?
出于对性能的考虑。在生命周期中去递归比较对象是十分消耗性能的。
19. state={ value: 1 }; this.state.value = 100; 然后 this.setState(this.state); 页面会发生渲染吗?
会。
20. 上面这样写会有什么问题?
这种直接改变原有对象的方式导致react无法对其进行任何优化,因此会有潜在的性能问题;如果你用了 PureComponent, 会发现状态无法直接更新。原因在于 PureComponent 重写了 shouldComponentUpdate,shouldComponentUpdate 中通过直接判断 state 和 props 前后的引用差别来判断,因此会返回false,导致render无法运行。
21. React 的原理,有去了解过吗,委托,fiber?
委托: React在管理事件绑定时,不是将事件直接绑定在DOM上的,而是将事件都绑定在document上,通过合成事件进行委托管理。当事件发生的时候,都冒泡到document上, react再通过document去统一分发事件。(在事件管理中心存储所有的dom事件,document作为事件委托者,通过dom的唯一标识,在事件管理中心触发事件) 比如我们平时用的e.stopPropogation,是React对于原生事件的封装。而原生事件需要通过e.nativeEvent.xx 获取。 目的是 消除浏览器差异带来的影响,通过委托给document也节约了内存。但是,在React 17 中,React 更改了事件委托,将事件委托到了根节点上,让react的事件树更符合dom规范。
fiber: React 15 之前,虚拟dom的diff操作是同步完成的,当页面有大量dom节点时,diff时间可能会过长,造成卡顿。为了解决这个问题,react 推出了fiber,将任务进行分片,每执行完一段更新过程,就把控制权交给任务协调模块,如果有紧急任务(用户操作等),就去执行紧急任务,没有则继续更新。
22. this.setState 调用了两次,会渲染两次吗?
不会。
23. setState的第二个参数成功的回调函数,是同步的还是异步的?是在DOM渲染之前回调,还是DOM渲染之后回调?是宏任务还是微任务?有去了解过吗?或者是怎么推测分析出来的?
异步的,DOM渲染之后回调,=============暂未解决=================================
24. 微任务和宏任务的执行关系是什么样子的?
js中有个机制叫事件循环,因为js引擎在执行js代码的时候会产生执行栈,我们的同步代码都会放入执行栈中执行,当遇到异步任务的时候,会将异步任务放至该同步任务的任务队列中,当同步任务执行完成,就去查看任务队列中是否有要执行的异步任务,依次将其放入执行栈中执行。 宏任务包括script,setTimeout,setTimeInterval,setImmidate,I/O,rendering等。微任务主要是 Promise。 通过一系列的实验,我们可以总结一下如何分析异步执行的顺序:
- 首先我们分析有多少个宏任务;
- 在每个宏任务中,分析有多少个微任务;
- 根据调用次序,确定宏任务中的微任务执行次序;
- 根据宏任务的触发规则和调用次序,确定宏任务的执行次序;
- 确定整个顺序。
25. useCallback 和 useMemo 用过吗?
useCallback 用于缓存函数,比如,当函数作为props传递给子组件时,如果父组件更新,函数会被重新创建,导致子组件中有依赖于该函数的 uesEffect 也会被重新调用。
useMemo 用于缓存值,其在 react hooks 中的作用有些类似于PureComponent。
26. useCallback 在 React 中实际的作用是什么?
27. useEffect 第二个参数是空数组的时候,在里面启动了一个 setInterval,去调用了一个state,但是当外界的state改变的时候,setInterval 里用的值是新的还是旧的?
旧的。
28. React 里因为什么会导致这个问题?
闭包?react 中的思想是将render的每一次看做一个帧,而每一个帧都对应一个useEffect。
29. 通用业务模板库的提效数据是如何计算的?
略
30. 组件库是怎么去进行编译的?babel 基于 webpack,支持按需加载吗?怎么做到的?
babel-plugin-import,解析成 AST 树,import {Button} from 'antd' => import Button from 'antd/bin/button'。
31. 组件库的 button webpack 是怎么打成单个文件的?
32. 讲一下你设计的比较好的一个组件?
其实一个组件设计的好的时候,字段的命名在很大程度上就能够给大家带来一个比较好的使用感受,某些字段封装的好的话也能更清楚,设计也是很重要的。
cy的评级?
略
为什么想离职?
不怎么追逐技术,希望能够技术上有更多的成长。
al内部的很完善的东西,比开源出来的东西更强大,你有去学习了解过或者钻研过吗?
除了工作中用到的东西,有自己额外了解学习的东西吗?或者比较感兴趣的?
你期望加入的团队能给你带来什么?
技术氛围浓,有挑战的事情
有什么问题想问我?
对我的评价,后续的建议?