本文参加了由公众号@若川视野 发起的每周源码共读活动,点击了解详情一起参与。
本期要阅读的源码: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"
}
}
}