- 本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
- 这是源码共读的第36期,链接:juejin.cn/post/711878…。
首先看代码
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;
代码很简单,Object.assign浅拷贝对象,将要删除的对象key列表遍历删除并且返回新对象。
第二看依赖
下面我们打开package.json查看运行指令
"scripts": {
"start": "father doc dev --storybook",
"build": "father doc build --storybook",
"compile": "father build",
"gh-pages": "father doc deploy",
"prepublishOnly": "npm run compile && np --yolo --no-publish",
"lint": "eslint .",
"test": "father test",
"coverage": "father test --coverage"
}
发现指令大部分以father开头,而不是node或者npm,说明封装过一层,我们查看father是什么
father
查看依赖文档
配置文件
文档中提到.fatherrc.js是配置文件,那我们按照配置文件查看
export default {
entry: ['src/index.js'],//指定入口文件,用过webpack的都懂
cjs: 'babel',//是否输出 cjs 格式,以及指定 cjs 格式的打包方式等
esm: { //是否输出 esm 格式,以及指定 esm 格式的打包方式等
type: 'babel', //指定 esm 的打包类型,可选 `rollup` 或 `babel`
importLibToEs: true //是否在 esm 模式下把 import 项里的 `/lib/` 转换为 `/es/`
},
doc: { base: '/switch' },//透传配置给 docz
preCommit: {
eslint: true,
prettier: true,
},
};
测试用例
用father运行测试用例
import omit from '../src';
describe('omit', () => {
it('should create a shallow copy', () => {
const benjy = { name: 'Benjy' };
const copy = omit(benjy, []);
assert.deepEqual(copy, benjy);
assert.notEqual(copy, benjy);
});
it('should drop fields which are passed in', () => {
const benjy = { name: 'Benjy', age: 18 };
assert.deepEqual(omit(benjy, ['age']), { name: 'Benjy' });
assert.deepEqual(omit(benjy, ['name', 'age']), {});
});
it('传多个重复参数', () => {
const benjy = { name: 'Benjy', age: 18 };
assert.deepEqual( omit(benjy, ['age','age']), { name: 'Benjy' });
assert.deepEqual( omit(benjy, ['age','age','age']), { name: 'Benjy' });
});
it('传对象没有的key参数', () => {
const benjy = { name: 'Benjy', age: 18 };
assert.deepEqual( omit(benjy, ['age','a']), { name: 'Benjy' });
assert.deepEqual( omit(benjy, ['a','b','c']), { name: 'Benjy', age: 18 });
});
it('传对象key参数不为字符串', () => {
const benjy = { name: 'Benjy', age: 18 };
assert.deepEqual( omit(benjy, [{}]), { name: 'Benjy', age: 18 });
assert.deepEqual( omit(benjy, [[]]), { name: 'Benjy', age: 18 });
});
});
在原作者测试用例之外又添加了三个我有疑问的测试用例,也是验证成功
其中测试用例用到了
asset断言,
assert.deepEqual,参照其他网友的笔记是递归判断是否相等
assert.notEqual,理解为!=
所以实现了设计的返回新对象,不修改原始对象的目的。
意外收获
it('给数组传递参数', () => {
const benjy = [1,2,3,4];
assert.deepEqual( omit(benjy, [1,2]), [1,,,4]);
assert.deepEqual( omit(benjy, ['1','2']), [1,,,4]);
});
想试试传入数组是否也生效,毕竟数组也是对象嘛,结果测试用例失败
能看到得到的是原始对象,而不是数组,查看源码发现是 Object.assign({}, obj)的原因,所以改下源码再次测试
function omit(obj, fields) {
const shallowCopy = JSON.parse(JSON.stringify(obj));//Object.assign({}, obj);
for (let i = 0; i < fields.length; i += 1) {
const key = fields[i];
delete shallowCopy[key];
}
return shallowCopy;
}
export default omit;
现在就测试通过了,但是 JSON.parse(JSON.stringify(obj))有自身的局限性,属于深拷贝,不符合作者期望的对象地址更改,但对象属性地址不更改的初衷。但也算是学到将数组转成对象的方法了。因祸得福
结尾
总结出以下几点
- 源码共度越来越卷了,去年因为身体原因(其实也是被KOA洋葱模型劝退了)有半年多没参加活动了,今年找个最简单的看看,但是留言的笔记写的一个比一个好,说明川川的号召力越来越强了,而且大家水平都提升了好多。
- 本来想几行的源码随便写写就完了,结果给自己挖的坑越来越大,顺便了解了下测试用例和father
- 后面身体条件允许的话,尽量多参加活动,多写笔记。