源码共读 使用omit.js剔除对象中的属性

152 阅读1分钟

0 环境

  • 编辑器:webstorm或者vscode
  • 系统版本:windows10
  • 编辑器版本:最新
  • 浏览器:谷歌
  • node等:最新

1 准备

npm包

omit.js源码

浅拷贝文章

浅拷贝文章1

2 前言

我们拉取omit.js源码,然后yarn install,运行即可

3 看文档

先看源码下面的文档,根据它给的API和案例,可以得出个结论,omit 它需要接收两个参数,第一个参数是目标对象(Object类型),第二个参数是数组并且是字符串类型(存在要移除的key),返回值是一个Object。根据第二个参数里的key,剔除掉目标对象里对应的key以及它的value。

image.png

4 核心源码

找到src的目录下的index.js文件。参考上面的解释,omit包含两个参数,将obj浅拷贝了一份(shallowCopy),循环fields,挨个得到key,然后shallowCopy拿到key,删除。 image.png

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;

现在的疑点,为啥需要浅拷贝,我直接操作对象不可以? 首先浅拷贝的定义:我自己创建一个新的对象,接收要重新copy或引用的对象值,假如是基本的数据类型,直接复制值给新对象就好了,若是引用数据类型,复制的就是内存中的地址,你的一个改变会影响到目标对象。根据我的调试,我认为这里浅拷贝的意义在于:我多次调用omit(希望这里的目标对象不受影响),正好针对基本的数据类型,删除操作的话,不会影响到目标对象,就很实用了。

要是遇到嵌套多的那种对象,对我来说,不涉及到函数、undefined、symbol、日期、不可枚举这些,丐版JSON.stringify应该就够了。

还有比如目标对象为空或者fields为空时的处理。

function omit(obj, fields) {
  // eslint-disable-next-line prefer-object-spread
  if (Object.keys(obj).length === 0 || fields.length === 0) {
    return Object.assign({}, obj)
  }

  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;

5 测试omit

首先找到test的文件,如下图: image.png

断言结果: 若不满足条件,就会抛出错误。assert.deepEqual():深度比较下的相等:基本类型值比较,引用类型也是比较它们的属性的值比较。assert.notEqual():浅比较不相等,判断基本类型或引用类型(对比地址)不相等,则满足期望。

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 };
    const copy = omit(benjy, ['age'])
    const copy1 = omit(benjy, ['name', 'age'])
    const copy2 = omit(benjy, ['name', 'age1'])
    assert.deepEqual(omit(benjy, ['age']), { name: 'Benjy' });
    assert.deepEqual(omit(benjy, ['name', 'age']), {});
  });
});

如下图:解释了上面浅拷贝的好处:这里虽然多次使用omit,但是benjy没有改变,copy和copy1变量都得到了想要的值,而copy2里age1这个key,benjy里没有,抛出了异常。 image.png