「我正在参与掘金会员专属活动-源码共读第一期,点击参与」
准备工作
git clone <https://github.com/benjycui/omit.js.git>
cd ./omit.js && code .
npm i
# 查看lodash 中的 omit
git clone <https://github.com/lodash/lodash.git>
cd ./lodash && code .
# 切换到 1.0.0 版本
git checkout 1.0.0
omit.js 分析
function omit(obj, fields) {
// eslint-disable-next-line prefer-object-spread
const shallowCopy = Object.assign({}, obj); // #1
for (let i = 0; i < fields.length; i += 1) {
const key = fields[i];
delete shallowCopy[key]; // #2
}
return shallowCopy; // #3
}
export default omit;
-
使用
Object.assign()创建一个obj的浅拷贝Object.assign()拷贝的是属性值,如果属性值是对象,那么拷贝的就是对象的引用
const obj = { "a": 1, "b": 2, "c": { "c1": 1, "c2": 2 } } const obj2 = omit(obj,['a']) obj.c === obj2.c // true -
遍历
fields,删除浅拷贝后的obj对象中的属性 -
最后返回该对象
lodash中的 omit
最新的实现很多代码都是处理各种边界情况和深浅拷贝的,看起来实在无聊,所以本次阅读的是 1.0.0 中的实现
/**
* Creates a shallow clone of `object` excluding the specified properties.
* Property names may be specified as individual arguments or as arrays of
* property names. If a `callback` function is passed, it will be executed
* for each property in the `object`, omitting the properties `callback`
* returns truthy for. The `callback` is bound to `thisArg` and invoked
* with three arguments; (value, key, object).
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The source object.
* @param {Function|String} callback|[prop1, prop2, ...] The properties to omit
* or the function called per iteration.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns an object without the omitted properties.
* @example
*
* _.omit({ 'name': 'moe', 'age': 40 }, 'age');
* // => { 'name': 'moe' }
*
* _.omit({ 'name': 'moe', 'age': 40 }, function(value) {
* return typeof value == 'number';
* });
* // => { 'name': 'moe' }
*/
function omit(object, callback, thisArg) { // #1
var isFunc = typeof callback == 'function',
result = {};
if (isFunc) {
callback = createCallback(callback, thisArg); // #2
} else {
var props = concat.apply(arrayRef, arguments); // #3
}
forIn(object, function(value, key, object) { // #4
if (isFunc
? !callback(value, key, object)
: indexOf(props, key, 1) < 0
) {
result[key] = value;
}
});
return result; // #5
}
-
1.0.0设计成可以传入字符串,也可以传入函数 -
如果传入的是函数, 执行
createCallback,生成一个重新指定了 this 指向的函数 -
如果传入的是字符串,则收集成数组,这里使用
concat复制arguments,其实就是简略实现了es6 中的…收缩运算符,不得不佩服其实力,走在了 es6 前//现在只需使用...运算符即可 function omit(obj,...values) -
和本次仓库的实现正相反,遍历的是传入的源对象,而不是要剔除的属性集合,忽略掉要剔除的属性,收集要保留的,放入
result -
最后返回
result
重写 omit.js
按照 lodash 的思路,遍历源对象, 而不是遍历要剔除的属性
function omit(obj,props){
const result = {}
Object.keys(obj).map(key=>{
if(!props.includes(key)){
result[key] = obj[key]
}
})
return result
}
改造一行代码,就是 lodash 的 pick 函数了(反向版 omit)
function pick(obj,props){
const result = {}
Object.keys(obj).map(key=>{
if(props.includes(key)){ // 把取反去掉
result[key] = obj[key]
}
})
return result
}
const object = { 'a': 1, 'b': '2', 'c': 3 };
pick(object, ['a', 'c']);
// => { 'a': 1, 'c': 3 }
最后
本次 omit.js 源码阅读到此结束,我知道本次仓库还有其他可挖掘的部分比如 npm依赖 ,测试用例 等,后续文章再继续看吧
<完>