- 本文参加了由 公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
- 这是源码共读的第36期,连接:可能是历史上最简单的一期 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: 平时写项目时,拷贝对象都是使用的扩展运算符,想知道这两种方法的区别?这里参考群里底层的原文章
- 对象合并,数组合并,Object.assign、connat的性能会比展开运算符"..."的性能高。
- Object.assign会触发Proxy/Object.definedProperty的set方法,展开运算符"..."不会触发。
- 它两都是浅拷贝。
- 合并对象、数组的时候,展开运算符放在前面的性能比放在后面的性能高。
- 不定参数的时候,有自己的使用方式。
- Object.assign 可以兼容es5,扩展运算符只能es6之后使用。
- 问题3:delete删除一个对象中,不存在的属性会发生什么?
不会发生什么,即使不存在也会返回true
总结
基础还是太薄弱了,还是要多多思考,多总结。