最简单源码 omit.js 剔除对象中的属性解读

科学上网

  • 克隆github的项目,需要配置git bash的代理,否则容易超时无法连接,在git bash中输入以下命令,后面的地址是我本地的代理地址,更换为自己的
bash 复制代码
git config ---global http.proxy http://127.0.0.1:7890
git config --global https.proxy http://127.0.0.1:7890

克隆项目

  • 这里直接克隆了omit.js的源码, 并使用 Visual Studio Code 打开
bash 复制代码
git clone https://github.com/benjycui/omit.js.git

运行项目

  • Visual Studio Code 中打开一个终端
bash 复制代码
# 安装依赖
npm install

# 执行测试用例
npm run test
  • 根据结果显示,通过了一个测试集合,2个测试案例。

查看测试内容

js 复制代码
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']), {});
  });
});
  • 查看源码, 打开src/index.js文件,里面便是omit.js的源码,只有11行。

看了一下源码,有以下几个问题

  • 问题1:第3行为什么要对传入的参数obj进行浅拷贝?

思考:平时写代码时,没有关注过这个,删除对象属性时直接使用delete就删除了,用着也没问题。然后就是将这行 浅拷贝 删除, 直接在参数obj上修改,进过测试,第一个测试用例中assert.notEqual(copy, benjy)无法通过,但是这也不影响剔除对象属性。思来想去,后面想到如果传入的obj,在后续的代码中需要使用,但此时obj已经发生改变,已经不是之前的obj了。代码解释如下:

js 复制代码
// 初始化一个对象,直接删除属性,不进行浅拷贝
const obj = {num: 1, sum: 0, init: 0 }
const copy = obj

// 剔除对象属性
delete copy['init']

// 对obj进行操作
obj['sum'] = obj['num'] + obj['init']

// 打印obj
console.log(obj)  // { num: 1, sum: NaN }
js 复制代码
// 初始化一个对象
const obj = {num: 1, sum: 0, init: 0 }

// 进行浅拷贝
const copy = Object.assign({}, obj)

// 剔除对象属性
delete copy['init']

// 对obj进行操作
obj['sum'] = obj['num'] + obj['init']

// 打印obj
console.log(obj)  // { num: 1, sum: 1, init: 0 }

举得例子可能有些生硬,总之如果确定该对象上的属性,后续不会再使用,可以直接删,改变原对象的属性。突然想起js的原生方法中,数组的循环 filter, map 均不会改变原数组。

  • 问题2: 平时写项目时,拷贝对象都是使用的扩展运算符,想知道这两种方法的区别?这里参考群里底层的原文章
  1. 对象合并,数组合并,Object.assign、connat的性能会比展开运算符"..."的性能高。
  2. Object.assign会触发Proxy/Object.definedProperty的set方法,展开运算符"..."不会触发。
  3. 它两都是浅拷贝。
  4. 合并对象、数组的时候,展开运算符放在前面的性能比放在后面的性能高。
  5. 不定参数的时候,有自己的使用方式。
  6. Object.assign 可以兼容es5,扩展运算符只能es6之后使用。
  • 问题3:delete删除一个对象中,不存在的属性会发生什么?

不会发生什么,即使不存在也会返回true

总结

基础还是太薄弱了,还是要多多思考,多总结。

相关推荐
callmeSoon6 天前
Vue2 模板编译三部曲(三)|生成器 Generator
vue.js·源码阅读
Tans56 天前
Java ReentrantLock 源码阅读笔记(上)
java·源码阅读
程序猿阿越9 天前
ChaosBlade源码(一)blade命令行
java·后端·源码阅读
码农明明16 天前
Android源码分析:从源头分析View事件的传递
android·操作系统·源码阅读
欧阳码农2 个月前
vue3的defineAsyncComponent是如何实现异步组件的呢?
vue.js·源码·源码阅读
鳄鱼不怕_牙医不怕2 个月前
Flutter 源码梳理系列(三十七):OffsetLayer
flutter·源码阅读
鳄鱼不怕_牙医不怕2 个月前
Flutter 源码梳理系列(三十六):RenderObject:PAINTING
flutter·源码阅读
鳄鱼不怕_牙医不怕2 个月前
Flutter 源码梳理系列(三十四):ContainerLayer
flutter·源码阅读
鳄鱼不怕_牙医不怕2 个月前
Flutter 源码梳理系列(三十一):PaintingContext
flutter·源码阅读
callmeSoon2 个月前
Vue2 模板编译三部曲(一)|架构设计 & 解析器 Parser
vue.js·源码阅读