最简单源码 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

总结

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

相关推荐
Tans51 天前
Androidx Fragment 源码阅读笔记(下)
android jetpack·源码阅读
Tans54 天前
Androidx Fragment 源码阅读笔记(上)
android jetpack·源码阅读
Tans58 天前
Androidx Lifecycle 源码阅读笔记
android·android jetpack·源码阅读
凡小烦8 天前
LeakCanary源码解析
源码阅读·leakcanary
程序猿阿越16 天前
Kafka源码(四)发送消息-服务端
java·后端·源码阅读
CYRUS_STUDIO19 天前
Android 源码如何导入 Android Studio?踩坑与解决方案详解
android·android studio·源码阅读
Code_Artist19 天前
[Java并发编程]6.并发集合类:ConcurrentHashMap、CopyOnWriteArrayList
java·后端·源码阅读
Joey_Chen1 个月前
【源码赏析】开源C++日志库spdlog
架构·源码阅读
顾林海1 个月前
Android MMKV 深度解析:原理、实践与源码剖析
android·面试·源码阅读
程序猿阿越1 个月前
Kafka源码(三)发送消息-客户端
java·后端·源码阅读