本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
这是源码共读的第36期 | 可能是历史上最简单的一期 omit.js 剔除对象中的属性
准备
omit.js 提供了删除对象属性的方法,它的作用和 delete差不多,不同的是它通过函数返回了一个新对象,不会对原对象进行操作,它没有副作用
https://github.com/benjycui/omit.js
解读package.json
基本信息
"name": "omit.js", //包名
"version": "2.0.2", //迭代版本 参考Semver语义化版本号
"description": "Utility function to create a shallow copy of an object which had dropped some fields.", //描述
"main": "lib/index.js", //入口文件 如果没找到默认会去找目录下的index.js
"module": "es/index.js", //ESM规范声明入口文件 一般会用于rollup webpack 导出模块使用
"types": "index.d.ts", //TS类型声明入口文件
依赖相关
@umijs/fabric
``umijs```下 一个包含 prettier,eslint,stylelint 的配置文件合集 fabric
require.resolve 简化了 path.join+__dirname的这一写法,并且它本身对于不存在的文件还会抛出错误。 fabric用提前封装好的配置文件,非常简单的实现了 prettier eslint stylelint的配置
assert
assert是一个编写单元测试的断言模块,当然我们选择用更流行的jest
father
father是umijs下基于rollup、docz、storybook、jest、prettier和eslint的打包和文档工具
np
np 它的描述就是最好的npm发布工具
rc-tools
用于离线测试React组件的包,没看到在哪有用到
omit.js的实现
function omit(obj, fields) {
// eslint-disable-next-line prefer-object-spread
const shallowCopy = Object.assign({}, obj);
for (let i = 0; i < fields.length; i += 1) {
const key = fields[i];
delete shallowCopy[key];
}
return shallowCopy;
}
export default omit;
//使用 const newObj = omit(targetObj,[keyName1,keyName2,..])
- 函数内部创建一个局部变量shallowCopy 通过Object.assign复制了obj创建一个新对象
- fields传入一个对象属性名数组,通过循环遍历将shallowCopy上对应数组的属性挨个删除
- 最后返回这个新对象
代码是浅拷贝实现,如果是复杂的嵌套对象则不起作用,同时这里也牵扯到了纯函数的一个知识点,也就是消除副作用,不对原来的对象产生任何影响。
TS支持以及单元测试
-
更换单元测试为Jest
npm i jest -D
npx jest --init //初始化jest并创建配置文件jest.config.js
1.1 安装完成后package.json内的 test会被重写为jest
1.2 引入babel解决 import语法编译错误
npm i babel-jest -D //支持jest的babel包
npm i @babel/core -D //babel核心编译包
npm i @babel/preset-env //babel预设的转换规则
1.3 修改tests下index.test.js
import omit from "../src";
describe("omit", () => {
it("should create a shallow copy", () => {
const benjy = { name: "Benjy", age: 18 };
const copy = omit(benjy, ["name"]);
expect(copy).toEqual({ age: 18 });
});
it("should drop fields which are passed in", () => {
const benjy = { name: "Benjy", age: 18 };
const target1 = omit(benjy, ["age"]);
const target2 = omit(benjy, ["age", "name"]);
expect(target1).toEqual({ name: "Benjy" });
expect(target2).toEqual({});
});
});
-
引入Typescript
npm i typescript -D
npx tsc --init //初始化 tsconfig文件
npm i ts-jest -D //jest typescript支持
npm i @types/jest //jest ts类型支持
2.1 修改jest.config.js
module.exports = {
preset: "ts-jest",
testEnvironment: "jest-environment-node"
};
2.2 修改index.js以及tests/index.test.js 改为ts后缀
//index.ts
function omit(obj: Object, fields: string[]) {
// eslint-disable-next-line prefer-object-spread
const shallowCopy = Object.assign({}, obj);
for (let i = 0; i < fields.length; i += 1) {
const key = fields[i];
delete shallowCopy[key as keyof typeof obj];
}
return shallowCopy;
}
export default omit;
//index.test.ts
import omit from "../src";
describe("omit", () => {
it("should create a shallow copy", () => {
const benjy = { name: "Benjy", age: 18 };
const copy = omit(benjy, ["name"]);
expect(copy).toEqual({ age: 18 });
});
it("should drop fields which are passed in", () => {
const benjy = { name: "Benjy", age: 18 };
const target1 = omit(benjy, ["age"]);
const target2 = omit(benjy, ["age", "name"]);
expect(target1).toEqual({ name: "Benjy" });
expect(target2).toEqual({});
});
});
发布和钩子
npm的scripts中给了一下几个类似钩子的命令,允许你在安装发布时处理一些其他的操作:
-
prepublish: 当你要发布或者打包或者在本地安装的时候,出触发这个命令 -
prepare: 会在prepublish与prepublishOnly之间触发,以下几种情况会触发这个命令:- 打包或者发布之前
- 安装git链接的dependencies
- 本地包的npm install,并且不带任何参数
-
prepublishOnly: 在prepare和prepack之间触发,只有运行npm publish,才会触发这个命令 -
prepack: 在打包之前运行,触发条件:npm packnpm publish- 安装一个git链接的依赖
-
postpack: 打包完成之后触发 -
publish, postpublish: 发布成功之后触发 -
preinstall: 安装之前触发 -
install, postinstall: 安装之后触发 -
preuninstall, uninstall: 卸载之前触发 -
postuninstall: 卸载之后触发
更多具体的用法可以官方NPM文档 当我们执行npm publish发布时 就会触发这个钩子 执行cpmplie进行代码构建并执行np发包
"compile": "father build",
"prepublishOnly": "npm run compile && np --yolo --no-publish",
总结
- npm内置script钩子prepublishOnly 在运行npm publish触发
- omit函数的使用并进行 TS类型支持
- 学习使用Jest单元测试并进行 TS类型支持
- package.json字段属性学习 认识main入口和moudule入口