手写源码 -- arrify 转数组

·  阅读 566
手写源码 --  arrify 转数组

上一篇文章写了omit.js 剔除对象中的属性,相对而言比较简单。这一篇实现一个比较简易的库。

添加测试文件

依然和上篇文章一样,使用vitest测试,具体怎么操作可以移步上一篇文章,这里我们就只写写测试文件了。

import { test, expect } from "vitest"
import { arrify } from "."

test("main", () => {
  expect(arrify("foo")).toEqual(["foo"])

  expect(arrify(null)).toEqual([])

  expect(arrify(undefined)).toEqual([])

  expect(arrify([1, 2])).toEqual([1, 2])
  
  expect(arrify(new Map([[1, 2]]))).toEqual([[1, 2]])

  expect(arrify(new Set([1, 2]))).toEqual([1, 2])

})

复制代码

实现arrify

毫无疑问我们需要实现一个arrify函数并导出,并且需要传入参数。

传入字符串

首先看这个测试

expect(arrify("foo")).toEqual(["foo"])
复制代码

arrify传入一个字符串,返回的是一个数组,而且这个数组将我们传入的字符串包裹起来。那我们可以很简单的实现出来。

export function arrify(value) {
  if (typeof value === "string") {
    return [value]
  }
}
复制代码

传入nullundefined

下面看下这个测试

expect(arrify(null)).toEqual([])

expect(arrify(undefined)).toEqual([])
复制代码

如果传入的是null或者undefined则直接返回[]

export function arrify(value) {
  if (value === null || value === undefined) {
    return []
  }
  ···
}
复制代码

传入数组

expect(arrify([1, 2])).toEqual([1, 2])
复制代码

如果传入的是数组,则直接返回

export function arrify(value) {
  ···
  if (Array.isArray(value)) {
    return value
  }
  ···
}
复制代码

可迭代对象

expect(arrify(new Map([[1, 2]]))).toEqual([[1, 2]])

expect(arrify(new Set([1, 2]))).toEqual([1, 2])
复制代码

这里要着重介绍一下。Symbol.iterator 为每一个对象定义了默认的迭代器。当需要对一个对象进行迭代时(比如开始用于一个for..of循环中),它的@@iterator方法都会在不传参情况下被调用,返回的迭代器用于获取要迭代的值。

一些内置类型拥有默认的迭代器行为,其他类型(如 Object)则没有。下表中的内置类型拥有默认的@@iterator方法:

我们可以像下面这样创建自定义的迭代器:

var myIterable = {}
myIterable[Symbol.iterator] = function* () {
    yield 1;
    yield 2;
    yield 3;
};
[...myIterable] // [1, 2, 3]
复制代码

所以我们想要让测试通过就可以判断value[Symbol.iterator]的类型是不是function即可

export function arrify(value) {
  ···
  if (typeof value[Symbol.iterator] === "function") {
    return [...value]
  }
}
复制代码

总结

以上就是我实现的一个手写arrify库。在手写过程中,会有很多自己的想法,思考测试该怎么写,思考代码该怎么重构,更重要的是你真的懂了源码,把它写下来就变成你自己的了。刚开始手写的库比较简单,后面会不断的给自己加大难度。

欢迎大家提出建议和意见,觉得还可以的话,点个赞。 github地址 欢迎大家来个star

分类:
前端
收藏成功!
已添加到「」, 点击更改