第33期 | arrify 转数组

127 阅读1分钟

本文参加了由公众号@若川视野 发起的每周源码共读活动,点击了解详情一起参与

本期要阅读的源码:arrify

源码解读

export default function arrify(value) {
    if (value === null || value === undefined) {
            return [];
    }

    if (Array.isArray(value)) {
            return value;
    }

    if (typeof value === 'string') {
            return [value];
    }

    if (typeof value[Symbol.iterator] === 'function') {
            return [...value];
    }

    return [value];
}

代码逻辑较为简单,重点关注于typeof value[Symbol.iterator] === 'function'代表传入的value是一个可遍历的遍历器对象。 原生具备 Iterator 接口的数据结构如下。

  • Array
  • Map
  • Set
  • String
  • TypedArray
  • 函数的 arguments 对象
  • NodeList 对象 自定义遍历器对象可如下:
class Range{
  constructor(from, to) {
      this.from = from
      this.to = to
  }
  includes(x) {
      return this.from <= x && x <= this.to
  }
  *[Symbol.iterator](){
      for(let x = Math.ceil(this.from); x <= this.to; x++){
          yield x
      }
  }
  toString(){
      return `(${this.from}...${this.to})`
  }
}

const r = new Range(1, 5)
arrify(r) // [1, 2, 3, 4, 5]

拓展资料收获

package.json

exports 字段定义了包的导出,优先级高于main。可以解决以下问题。

1. 导出相同名字,但作用不同的函数

   { 
       "name": "pkg", 
       "exports": { 
           ".": "./main.mjs",
           "./foo": "./foo.js"
       } 
   }
 import { something } from "pkg"; // from "pkg/main.mjs"
 import { something } from "pkg/foo"; // from "./foo.js"

2. 有条件的映射

  • 以moment举例,提供browser和node不同的映射
    {
      "name": "@momentjs/moment",
      "version": "0.0.0",
      "type": "module",
      "main": "./dist/index.js",
      "exports": {
        ".": {
          "node": "./dist/index.js",
          "browser": "./dist/index-browser.js"
        },
        "./": {
          "node": "./src/util/",
          "browser": "./src/util-browser/"
        },
        "./timezones/": "./data/timezones/",
        "./timezones/utc": "./data/timezones/utc/index.mjs",
        "./core-polyfill": {
          "node": ["std:core-module", "./core-polyfill.js"],
          "browser": "./core-polyfill-browser.js"
        }
      }
    }
  • 为我们的包提供 CommonJS 和 ESModule 输出
   { 
       "name": "pkg", 
       "exports": { 
          "module-a": { 
              "import": "./lib/public-module-a.mjs", 
              "require": "./lib/public-module-a.cjs" 
              }
       } 
   }