本文参加了由公众号@若川视野 发起的每周源码共读活动,点击了解详情一起参与。
1. 学习目标
- 任务发布: 【若川视野 x 源码共读】第36期 | 可能是历史上最简单的一期 omit.js 剔除对象中的属性
- omit.js 剔除对象中的属性
- github仓库 github.com/benjycui/om… 主要看这个
- npm www.npmjs.com/package/omi…
2. 选学资料
-
类似 TS Omit 参考文章 zhuanlan.zhihu.com/p/397398407
-
underscore.js 也有这个方法 omit underscorejs.org/docs/module…
-
lodash 也有 omit docs-lodash.com/v4/omit/
3. 学习过程
3.1 如何使用 omit.js 来剔除对象中的方法
- 安装
omit.js模块:npm i --save omit.js
使用如下:
var omit = require('omit.js');
omit({ name: 'Benjy', age: 18 }, [ 'name' ]); // => { age: 18 }
- 安装
lodash, 使用lodash中的_.omit(object, [props])
var object = { 'a': 1, 'b': '2', 'c': 3 };
_.omit(object, ['a', 'c']);
// => { 'b': '2' }
3.2 omit.js 源码
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;
3.3 举例
- 删除
object对象的属性
const obj = { name: 'Benjy', age: 18 };
const result = omit(obj, ['name']);
console.log("obj==", obj); // { name: 'Benjy', age: 18 }
console.log("result==", result); // { age: 18 }
// 使用omit的产生的新对象不改变源对象
console.log("obj === result-->", obj === result); // false
console.log("obj == result-->", obj == result); // false
// 嵌套对象
const obj = { name: 'Benjy', info: { age: 18, number: 10, hobhy: 'fishing' } };
const result = omit(obj, ['name']);
console.log("obj==", obj);
// 结果:{ name: 'Benjy', info: { age: 18, number: 10, hobhy: 'fishing' } }
console.log("result==", result); // { info: { age: 18, number: 10, hobhy: 'fishing' } }
// 无法剔除 info 对象里面的 age、number、hobby 属性
- 在 TS 中的应用
Omit是TypeScript3.5新增的一个辅助类型,
它的作用主要是:以一个类型为基础支持剔除某些属性,然后返回一个新类型。
import omit from 'omit.js';
type Person = {
name: string;
age: string;
hobby: string;
};
type PersonWithoutHobby = omit<Person, 'hobby'>;
// PersonWithoutHobby equal to NormalPerson
type NormalPerson = {
name: string;
age: string;
};
4. delete vs omit.js
日常开发中,删除对象中的某个属性,很多同学都是直接使用 delete obj.xxx 的。
那么:
1. delete 和 omit.js 的返回值是什么?
delete 返回的是布尔值(删除成功返回true,删除失败返回false),
omit.js 返回的是 剔除属性后的新对象。
const obj = { name: 'coco', age: 18 };
const result_omit = omit(obj, ['name']);
console.log("result_omit==", result_omit); // {age: 18}
const result_delete = delete obj.name;
console.log("result_delete==", result_delete); // true
2. delete 和 omit.js 删除不存在的属性,返回值是什么?
delete返回的是 true,omit.js 返回的是删除前的对象。
const obj = { name: 'coco', age: 18 };
const result_omit = omit(obj, ['p']);
console.log("result_omit==", result_omit); // { name: 'coco', age: 18 }
const result_delete = delete obj.p;
console.log("result_delete==", result_delete); // true
3. delete 不能删除原型上的属性,omit.js 也不能删除原型上的属性
omit.js 用的 Object.assign() 是浅拷贝,不拷贝原型上的属性, 所以也就不能删除原型属性了。
function Foo() {
this.name = 'coco';
}
Foo.prototype.age = 18;
const foo = new Foo(); // foo为 {name:'coco'}
console.log("foo.age==", foo.age); // 18
console.log(delete foo.age); // true
console.log("foo.age==", foo.age); // 18
console.log(omit(foo, ['age'])); // 删除不存在的属性age,返回的是删除前的属性 {name: 'coco'}
console.log(omit(foo, ['lala'])); // 删除不存在的属性age,返回的是删除前的属性 {name: 'coco'}
4. delete 不能删除一个变量
let a = 88;
console.log(delete a); // false
console.log(omit(a, ['a'])); // {}
5. delete 删除数组某个数据,数组长度不会变化
- delete 删除数组的某一项,并不会导致数组长度变短。
- 对应的数据的值会变成
empty,而不是undefined或null。
let arr = [1, 2, 3];
console.log("arr.length==", arr.length); // 3
console.log(delete arr[1]); // true
console.log("arr.length==", arr.length); // 3
console.log("arr==", arr); // [1, empty, 3]
empty是“未初始化”的意思。
new Array(2)会得到[empty x 2]。forEach和in并不会对未初始化的值进行任何操作。
6. 哪些属性不能被 delete 删除?
var、const、let声明的全局变量- 数据属性
configurable: false的属性 - 原型上的属性
- 函数参数
- 一些常量(NaN、Infinity、undefined)
- 函数声明
5. 总结
对 omit.js 有了初步的认识,也对delete 和 omit.js 做了简单的比较。 也就是说: delete 返回 false 一定删除失败了;delete 返回 true 不一定删除成功了。而且,delete 有很多不能删除的对象,也不能直接释放内存。
综上所述,日后若遇到删除对象中某个属性的时候,推荐使用 omit 方法(lodash的omit方法或者 omit.js)。