omit.js为什么把删除对象属性也封装为工具方法?

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

我们会遇到使用一个对象但却不需要对象的某一个属性的场景。作为一个有js开发使用经验的人,问我们怎么删除对象属性的时候我们都会想到delete。但delete之后,对象中就没有这个属性了。所以解决方案就是:拷贝这个对象所有用到的属性,但是不要那个(或哪些)用不到的属性。这样一句话对应到代码中就是好多行,如果有个写好的工具方法让我们用岂不是很快乐嘛~ omit.js 就干这个事!我们一起学习其使用和源码吧~

1.准备工作

  1. clone代码
https://github.com/benjycui/omit.js
  1. 了解omit是啥?

是实用的工具函数用于创建已删除某些字段的对象的浅副本。

var omit = require('omit.js');
omit({ name: 'Benjy', age: 18 }, [ 'name' ]); // => { age: 18 }
  1. 号外:omit此单词第一次碰到,真不知道啥意思,含义见下图:

可以看这篇文章abolish,cancel,delete与omit有什么共同点你能进行顺序排列吗,了解更多词汇方面的解释。下面看一下omit的源码:

2.源码解读

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;

首先使用Object.assign对源对象obj进行浅拷贝。(Note: 这块默认你就会传对象,没有进行参数检查。缺少try...catch或相应异常处理逻辑)

遍历fields数组,取对象属性逐一删除。(Note: 感觉这块强制files是数组不太好,有时候我们使用的时候就想删除一个属性,最好支持一下字符串,如果是字符串就将此字符串当作属性删除。)

下面验证一下Object.assign为浅拷贝,见下图:

如上图所示,使用Object.assign将obj的属性复制给obj2, 其中obj的属性c是数组,属于引用类型的数据。当修改obj时,我们发现obj2的c属性也发生变化了。所以Object.assign()方法是一个对象的浅拷贝方法。omit的源码可以说非常简单,但是package.json中的一些npm包还是挺有学习价值的,我们来简单了解一下:

3.npm包积累

  1. father: Library toolkit based on rollup, docz, storybook, jest, prettier and eslint。

在omit.js的package.json文件中的好几个 npm script都有用到father,例如:

"start": "father doc dev --storybook",
"build": "father doc build --storybook",
"compile": "father build",
"gh-pages": "father doc deploy",

能够看到father又能打包编译又能生成文档,下图是执行run start命令的执行结果:

  1. storybook: Storybook is an open source tool for building UI components and pages in isolation. It streamlines UI development, testing, and documentation。(引自:storybook.js.org/

我们执行run start之所以能够把readme.md显示在浏览器中就又storybook的功劳。

  1. assert: The assert module from Node.js, for the browser. 所以使用方法还是要看nodejs.org/api/assert.…

在omit.js的tests/index.test.js中使用assert进行测试用例的书写:

import assert from 'assert';
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']), {});
  });
});
  1. umi-fabric:一个包含 prettier,eslint,stylelint 的配置文件合集

omit.js的.eslintrc.js文件内容如下:

const base = require('@umijs/fabric/dist/eslint');

module.exports = {
  ...base,
  rules: {
    ...base.rules,
    'no-template-curly-in-string': 0,
    'prefer-promise-reject-errors': 0,
    'react/no-array-index-key': 0,
    'react/sort-comp': 0,
    'import/no-named-as-default': 0,
    'import/no-named-as-default-member': 0,
  },
};

可见umijs/fabric提供了一些规则,使用时可以补充自己的规则或者覆盖一些规则。

  1. np: A better npm publish

帮助进行nmp包发布,在omit.js中是这样使用的:

"prepublishOnly": "npm run compile && np --yolo --no-publish",

先执行compile(其实就是father-build),然后使用 np, 下图是运行的结果:

毫无疑问地以失败告终,有git 的 push tags权限。

  1. rc-tools: offline tools for react component

没看到在哪块有用到。

至此,omit.js算是学完了,怎么能用到我们的项目中呢?看下面的内容:

4.学习致用

想到我在代码里常常会写delete, 例如下面的代码:

try {
  const param = JSON.parse(JSON.stringify(this.form))
  delete param.lonLat
  await createCarStore({
    ...param,
  });
  this.$message.success('提交成功!');
  this.$router.go(-1);
} catch (error) {
  this.$message.error(error.data.remark);
}

使用omit.js 就可以写成这样:

try {
  const param = omit(this.form, ['lonLat'])
  await createCarStore({
    ...param,
  });
  this.$message.success('提交成功!');
  this.$router.go(-1);
} catch (error) {
  this.$message.error(error.data.remark);
}

两行变一行,何乐而不为?

5.总结

学完本期源码,笔者有如下收获:

  • 复习了Object.assgin方法,加深对深浅拷贝的理解
  • 了解到father, storybook等npm包的使用
  • 学习了如何发布npm包
  • 可以使用omit.js来优化项目代码

我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿

猜你喜欢

转载自juejin.im/post/7121246502798196743