如何实现Jest的Not方法
前阵子在面试某节公司资深前端岗位时,遇到了许多有趣的问题。其中印象比较深刻,且网络很少提到的问题,便是如何去实现Jest的not方法。
思考
我们在写单元测试的时候,经常会写下面两个类似语句:
expect(1).toBe(1);
expect(1).not.toBe(1);
为了实现 expect(1).not.toBe(1) 这样的链式断言,我们需要为 expect() 函数返回一个包含 .not 方法的对象,以及一个 toBe() 方法用于进行断言判断。
如果要实现第一个语句,我们直接的念头就是创建类,共享类中的变量。在调用toBe方法时,比较参数和变量即可实现这个功能。
此时我们调用的时候,还是要先创建一个类,需要一个名为expect的函数封装,即可完成整个需求。
那么not呢?我们可能需要外加一个状态判断即可完成。
代码
既然已经获取了思路,那么我们就只需要顺着这个思路完成即可。
- 声明类:
class JestExpect {
constructor(value) {
this.value = value;
this.negative = false;
}
get not() {
this.negative = true;
return this;
}
toBe(expected) {
const pass = this.value === expected;
if (this.negative) {
if (pass) {
throw new Error(`Not: ${this.value} should not be ${expected}`);
}
} else {
if (!pass) {
throw new Error(`${this.value} should be ${expected}`);
}
}
}
}
- 封装expect函数
// 自定义的 expect 函数
const expect = (value) => new JestExpect(value);
- 使用
try {
expect(1).toBe(1);
expect(1).not.toBe(1);
console.log("test pass");
} catch (err) {
console.log(err.message);
}
- 解释
我们定义了一个 JestExpect 类来处理链式断言。expect() 函数返回一个 JestExpect 对象,并提供了 .not 修饰符,通过在 JestExpect 对象上设置 negative 标志,来实现取反操作。然后我们实现了 toBe() 方法来进行断言判断,根据 negative 标志来决定是否取反。
面试中其他问题分享
- 解释下分布式的CRDT。
- 解释下YJS。
- 传统的富文本的OP算法是什么?
- 是否读过Acorn?
- 是否读过Babel Parser?
简要解释:
- CRDT是conflict-free replicated Data Type, 分布式系统里实现数据的一致性和并发更新,主要是多个副本的数据同步。
- yjs是CRDT的一个开源分布式协作框架。
- OP算法:传统的协作编辑算法,它使用转换规则来处理并发操作,需要对操作序列进行转换和解决冲突
- Acorn: 处理pollyfill降级的东西。本质是编译原理那套,读取代码,转成具体语法书CST,可以转成抽象语法树ast
- Babel parser: 使用acorn的ast,做ssa风格IR处理,最后实现babel的代码降级,比如:
class A -> A.prototype.constructor()
扩展
-
OP算法是一种传统的协作编辑算法,它使用转换规则来处理并发操作,需要对操作序列进行转换和解决冲突。
-
CRDT是一种数据结构设计理念,它通过设计特殊的数据类型来自动解决并发冲突,无需额外的转换和解决冲突的步骤。
虽然OP算法和CRDT都是用于处理协作编辑和数据同步的问题,但它们的实现原理和方法有所不同。
- CRDT更加简单和自动化,适用于一些特定场景和数据类型
- OP算法则更加灵活和通用,适用于处理各种类型的协作编辑任务。
具体使用哪种方法取决于具体的应用需求和实现复杂性。