源码学习-omit.js库【移除对象中的属性】

1,130 阅读5分钟

导读

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

【若川视野 x 源码共读】第36期 | 可能是历史上最简单的一期omit.js 剔除对象中的属性点击了解本期详情一起参与

终于有时间写下这篇文章的分享了,源码真的很简单,所以想在记忆还算清楚,赶紧记录下来。😂

在学习过程中,还不仅回顾了Javascript的基础知识【深与浅拷贝】,还有如何在Vscode调试index.test.js中的例子,收益匪浅。还接触了最新的打包工具father,让我们来看看吧👀

源码解析

// 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"
  },

安装完node_modules包,查看package.json中的script命令,使用father来进行项目管理,包括启动、构建、发布、单元测试等。

入口文件中,导出omit函数,如下:

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;

使用方法在README.md中,写明了使用方法:

var omit = require('omit.js');
omit({ name: 'Benjy', age: 18 }, [ 'name' ]); // => { age: 18 }

从上面的使用及源码中可看出,函数可以接受两个参数,即原对象需要剔除的属性,返回一个剔除了指定属性的浅拷贝的对象。

father包管理器

father是新一代包管理工具,可以代替yarn or npm。npm指路

整理一下omit库用到的father命令,将按照类别区分如下:

docz内置文档

以下三行命令,将内置docz文档配置。文档指路

dev模式将在开发环境下,展示项目中的.md文档,本库中是README.md文件,随后启动本地服务,在浏览器中就会看到如下图的界面:

docz.png

build模式将会本地构建.doc目录,可以将其目录下文件上传到服务器。 deploy部署模式,将会自动部署到gitHub目录。

使用 deploy 之前请先执行 build 命令,文档部署后域名为:https://yourname.github.io/your-repo

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

build构建

打包命令,可以传入--config指定多种文件格式,并且可以映射入口文件为指定的文件名称。

"compile": "father build"

test单元测试

father2.*.*版本内置了test单元测试,但是看到参与开发的工程师在知乎上说明,在新版4.*版本已经不再内置这些工程化,用户可以更加灵活的添加单元测试。

father.png

"test": "father test",
"coverage": "father test --coverage" // 单元测试覆盖率

assert断言

omit库使用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']), {});
  });
});

说实话,当时看到第一个例子,不太明白什么使用assert.deepEqual()assert.notEqual()都可以通过用例检测,觉得两个有点矛盾,后来去看了nodejs官网上的说明,有些明白了。 前者会遍历对象所有自身的且可枚举的属性,进行比较,即使用 ==比较符。如下

import assert from 'node:assert';

const obj1 = {
  a: {
    b: 1
  }
};
const obj2 = {
  a: {
    b: 2
  }
};
const obj3 = {
  a: {
    b: 1
  }
};
const obj4 = Object.create(obj1);

assert.deepEqual(obj1, obj1);
// OK

// Values of b are different:
assert.deepEqual(obj1, obj2);
// AssertionError: { a: { b: 1 } } deepEqual { a: { b: 2 } }

assert.deepEqual(obj1, obj3);
// OK

// Prototypes are ignored:
assert.deepEqual(obj1, obj4);
// AssertionError: { a: { b: 1 } } deepEqual {}

notEqual()使用==比较符,如下:

import assert from 'node:assert';

assert.notEqual(1, 2);
// OK

assert.notEqual(1, 1);
// AssertionError: 1 != 1

assert.notEqual(1, '1');
// AssertionError: 1 != '1'

那经omit函数返回的浅拷贝对象,可枚举属性值与原对象的是相等的,但是由于Object.assign的目标对象是个新{},使用==也不再相等。

深拷贝与浅拷贝

既然函数中使用了Object.assign()进行浅拷贝,再回顾一下他们之间的区别。

区别

深浅拷贝是针对Javascript中的引用类型而言,因为引用类型比较特殊,浅拷贝仅仅复制了一份引用类型在内存中的地址,两个对象的改变会同步。深拷贝将会完全创造一个新的对象,内存地址不再指向同一份内存地址,对象改变不再互相影响。

Object.assign

Object.assign()是浅拷贝,如果对象中有嵌套的对象,那拷贝的对象会随原对象发生变化。

Vscode调试技巧

最后一点点,是如何在Vscode中调试代码。

配置 auto-attach

Vscode中按 ctrl + shift + p,打开输入 >auto attach。默认是智能(smart

xxxx.png

然后在本库中运行npm run test,或者将鼠移入package.json的scripts上方,会出现【调试】的提示。在需要的位置打断点,并运行命令进行调试,Vscode界面将入进入断点模式。左侧面板会有函数调用栈、变量、断点,和在Chrome开发者工具上非常相似。

结尾

在学习omit库的最开始,只注意到了导出函数的使用,没有关注单元测试、调试等这些内容,看看别的同学学习的都很深入,自己也应该多了解,多翻阅文档。 分享今天看到的一句话

行动比思想有时候更重要。

所以,想做什么,现在就去做吧,从此刻开始🤞

还有最近在看的书单【尘埃落定】一部荣获茅盾文学奖的长篇小说,有喜欢的我们可以一起分享呀🎉