- JS 中如何实现继承
- 通过原型实现的继承和 class 有何区别
- 手写任意一种原型继承
我们可以通过 assign 、扩展运算符等方式来实现浅拷贝:
let a = {age: 1}let b = Object.assign({}, a)a.age = 2console.log(b.age) // 1b = {...a}a.age = 3console.log(b.age) // 2
深拷贝两个对象内部所有的引用都不相同就是深拷贝的含义 。最简单的深拷贝方式就是使用 JSON.parse(JSON.stringify(object)),但是该方法存在不少缺陷 。
比如说只支持 JSON 支持的类型,JSON 是门通用的语言,并不支持 JS 中的所有类型 。
同时还存在不能处理循环引用的问题:
如果想解决以上问题,我们可以通过递归的方式来实现代码:
// 利用 WeakMap 解决循环引用let map = new WeakMap()function deepClone(obj) {if (obj instanceof Object) {if (map.has(obj)) {return map.get(obj)}let newObjif (obj instanceof Array) {newObj = []} else if (obj instanceof Function) {newObj = function() {return obj.apply(this, arguments)}} else if (obj instanceof RegExp) {// 拼接正则newobj = new RegExp(obj.source, obj.flags)} else if (obj instanceof Date) {newobj = new Date(obj)} else {newObj = {}}// 克隆一份对象出来let desc = Object.getOwnPropertyDescriptors(obj)let clone = Object.create(Object.getPrototypeOf(obj), desc)map.set(obj, clone)for (let key in obj) {if (obj.hasOwnProperty(key)) {newObj[key] = deepClone(obj[key])}}return newObj}return obj}
上述代码解决了常见的类型以及循环引用的问题,当然还是一部分缺陷的,但是面试时候能写出上面的代码已经足够了,剩下的能口述思路基本这道题就能拿到高分了 。比如说递归肯定会存在爆栈的问题,因为执行栈的大小是有限制的,到一定数量栈就会爆掉 。
因此遇到这种问题,我们可以通过遍历的方式来改写递归 。这个就是如何写层序遍历(BFS)的问题了,通过数组来模拟执行栈就能解决爆栈问题,有兴趣的读者可以咨询查阅 。
PromisePromise 是一个高频考点了,但是更多的是在笔试题中出现,概念题反倒基本没有,多是来问 Event loop 的 。
对于这块内容的复习我们需要熟悉涉及到的所有 API,因为考题里可能会问到 all、race 等等用法或者需要你用这些 API 实现一些功能 。
对于 Promise 进阶点的知识可以具体阅读笔者的这篇文章,这里就不复制过来占用篇幅了:Promise 你真的弄明白了么?
常见考点
- 使用 all 实现并行需求
- Promise all 错误处理
- 手写 all 的实现
页面上有三个按钮,分别为 A、B、C,点击各个按钮都会发送异步请求且互不影响,每次请求回来的数据都为按钮的名字 。请实现当用户依次点击 A、B、C、A、C、B 的时候,最终获取的数据为 ABCACB 。这道题目主要两个考点:
- 请求不能阻塞,但是输出可以阻塞 。比如说 B 请求需要耗时 3 秒,其他请求耗时 1 秒,那么当用户点击 BAC 时,三个请求都应该发起,但是因为 B 请求回来的慢,所以得等着输出结果 。
- 如何实现一个队列?
class Queue {promise = Promise.resolve();excute(promise) {this.promise = this.promise.then(() => promise);return this.promise;}}const queue = new Queue();const delay = (params) => {const time = Math.floor(Math.random() * 5);return new Promise((resolve) => {setTimeout(() => {resolve(params);}, time * 500);});};const handleClick = async (name) => {const res = await queue.excute(delay(name));console.log(res);};handleClick('A');handleClick('B');handleClick('C');handleClick('A');handleClick('C');handleClick('B');
async、awaitawait 和 promise 一样,更多的是考笔试题,当然偶尔也会问到和 promise 的一些区别 。await 相比直接使用 Promise 来说,优势在于处理 then 的调用链,能够更清晰准确的写出代码 。缺点在于滥用 await 可能会导致性能问题,因为 await 会阻塞代码,也许之后的异步代码并不依赖于前者,但仍然需要等待前者完成,导致代码失去了并发性,此时更应该使用 Promise.all 。
下面来看一道很容易做错的笔试题 。
推荐阅读
- 不爱跳槽的程序员集中在8-17k,揭晓中国开发者的真实现状
- 大型Git仓库的部分克隆
- 数据仓库、数据集市、数据湖、数据中台这些概念,终于整明白了
- 银行数据仓库的系统架构是什么?看这篇足矣
- 数据仓库构建流程
- 长安|性价比超宏光MINI!长安奔奔E-Star国民版暂停收取订单:产能受限
- 数据仓库组件:Hive环境搭建和基础用法
- 10分钟自建企业级Docker镜像仓库!这个开源项目太顶了
- 一文带你搭建本地YUM仓库
- 开发框架搭建考量