大家好,我是前端西瓜哥。我最近尝试开启一个源码解读系列,不定期解读一些简单或复杂的源码。
今天要解读 npm 第三方库的源码:only,仓库地址为:https://github.com/tj/node-only
这个库是 tj 大神写的工具方法。tj 大神是一名程序员大佬,主要在 nodejs 领域做出了不少开源贡献,是 Express、Koa、node-canvas 等一系列知名开源项目的创建者和贡献者。
only 方法能干啥?
only 的功能很简单:返回一个对象的白名单属性。说具体点,就是提取指定对象的一些属性放到新对象里,并返回这个新对象。
const only = require('only'); var obj = { name: 'tobi', last: 'holowaychuk', email: 'tobi@learnboost.com', _id: '12345' }; only(obj, 'name last email'); /* { name: 'tobi', last: 'holowaychuk', email: 'tobi@learnboost.com' } */
only 方法要求传入一个对象,以及一个白名单列表,这个列表可以是属性名数组,也可以是通过空格间隔属性名表示的字符串。
第二个参数支持字符串格式,是因为使用更方便,能少写很多引号。使用上的优雅,是我们设计 API 时的一个重要考量点。
only 库的实现
module.exports = function(obj, keys){ obj = obj || {}; if ('string' == typeof keys) keys = keys.split(/ +/); return keys.reduce(function(ret, key){ if (null == obj[key]) return ret; ret[key] = obj[key]; return ret; }, {}); };
代码解读
首先是对第一个参数 obj 做简单容错。如果 obj 是一个值为 undefined 或 null 之类的假值,我们就将其设置为一个空对象,防止抛出错误。
然后就是将可能是字符串形式的白名单转换为数组的格式。
使用的方法为:keys.split(/ +/)
,这里用到了 split 的正则表达式参数写法,/ +/
这个正则表达式代表一个数量大于等于 1 的多个空格符。这其实是很常见的分割字符串拿到数组的写法。
最后用老鸟非常喜欢用的 Array.prototype.reduce()
的写法,来对 keys 数组进行迭代。
对于每个 key,只要原数组中不为 null 或 undefined,就将其浅拷贝到新对象中。
reduce()
方法的返回值就是我们要的新对象,直接将其返回。
我们再说说为什么一些资深前端喜欢用 reduce()
方法。其实是因为 reduce
这个方法相比 forEach
、map
这些方法要更灵活,它能返回任何类型的值而写法不失简洁。forEach 没有返回值,而 map 只能返回数组类型且大小相同的数组,虽然符合单一职责原则,但也因此失去了灵活性。
我曾经写过一篇关于 reduce 的文章,你感兴趣的话可以看看:为什么说数组实例的reduce方法灵活?
only 方法解读完毕。