【面试分享】如何实现Jest的Not方法,富文本问题

340 阅读3分钟

如何实现Jest的Not方法

前阵子在面试某节公司资深前端岗位时,遇到了许多有趣的问题。其中印象比较深刻,且网络很少提到的问题,便是如何去实现Jest的not方法。

思考

我们在写单元测试的时候,经常会写下面两个类似语句:

  expect(1).toBe(1);
  expect(1).not.toBe(1);

为了实现 expect(1).not.toBe(1) 这样的链式断言,我们需要为 expect() 函数返回一个包含 .not 方法的对象,以及一个 toBe() 方法用于进行断言判断。

如果要实现第一个语句,我们直接的念头就是创建类,共享类中的变量。在调用toBe方法时,比较参数和变量即可实现这个功能。

此时我们调用的时候,还是要先创建一个类,需要一个名为expect的函数封装,即可完成整个需求。

那么not呢?我们可能需要外加一个状态判断即可完成。

代码

既然已经获取了思路,那么我们就只需要顺着这个思路完成即可。

  1. 声明类:
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}`);
      }
    }
  }
}
  1. 封装expect函数
// 自定义的 expect 函数
const expect = (value) => new JestExpect(value);
  1. 使用
try {
  expect(1).toBe(1);
  expect(1).not.toBe(1);
  console.log("test pass");
} catch (err) {
  console.log(err.message);
}
  1. 解释

我们定义了一个 JestExpect 类来处理链式断言。expect() 函数返回一个 JestExpect 对象,并提供了 .not 修饰符,通过在 JestExpect 对象上设置 negative 标志,来实现取反操作。然后我们实现了 toBe() 方法来进行断言判断,根据 negative 标志来决定是否取反。


面试中其他问题分享

  1. 解释下分布式的CRDT。
  2. 解释下YJS。
  3. 传统的富文本的OP算法是什么?
  4. 是否读过Acorn?
  5. 是否读过Babel Parser?

简要解释:

  1. CRDT是conflict-free replicated Data Type, 分布式系统里实现数据的一致性和并发更新,主要是多个副本的数据同步。
  2. yjs是CRDT的一个开源分布式协作框架。
  3. OP算法:传统的协作编辑算法,它使用转换规则来处理并发操作,需要对操作序列进行转换和解决冲突
  4. Acorn: 处理pollyfill降级的东西。本质是编译原理那套,读取代码,转成具体语法书CST,可以转成抽象语法树ast
  5. Babel parser: 使用acorn的ast,做ssa风格IR处理,最后实现babel的代码降级,比如:
class A -> A.prototype.constructor()

扩展

  1. OP算法是一种传统的协作编辑算法,它使用转换规则来处理并发操作,需要对操作序列进行转换和解决冲突。

  2. CRDT是一种数据结构设计理念,它通过设计特殊的数据类型来自动解决并发冲突,无需额外的转换和解决冲突的步骤。

虽然OP算法和CRDT都是用于处理协作编辑和数据同步的问题,但它们的实现原理和方法有所不同。

  • CRDT更加简单和自动化,适用于一些特定场景和数据类型
  • OP算法则更加灵活和通用,适用于处理各种类型的协作编辑任务。

具体使用哪种方法取决于具体的应用需求和实现复杂性。