npm 模块 node-only 源码总结

356 阅读2分钟

该博客是个人学习 node-only  总结篇,如理解有误,请在评论区留言和纠错。

转载请标明出处。

场景

在开发项目时可能会遇到过类似的情况,如果没有请忽略前面的话。从一个对象上取部分属性组成一个新对象再进行后续处理。

假设有一个 user 的对象数据,只需要发送给服务端 email 、phone 、idjob 这些字段组成的对象,或许会这么写。

const user = {
  name: "张三",
  age: 23,
  email: "zhangsan@163.com",
  phone: "17000000000",
  tags: ["吃""喝""玩""乐"],
  high: 175,
  weight: "70kg",
  id: rt_sxc16hz_l,
  job: "医生"
}

const { email, phone, id, job } = user;
const info = {
  email,
  phone,
  id,
  job
}


当使用 node-only 就可以这么处理:

const only = require("node-only")

const user = {
  name: "张三",
  age: 23,
  email: "zhangsan@163.com",
  phone: "17000000000",
  tags: ["吃""喝""玩""乐"],
  high: 175,
  weight: "70kg",
  id: rt_sxc16hz_l,
  job: "医生"
}

const info = only(user, "email phone id job")

// 或者

const info = only(user, ["email", "phone", "id", "job"])

很方便的取对象的某些属性,其内部实现非常简单,就是 迭代 。

源码

module.exports = function(obj, keys){
  // 1
  obj = obj || {};
  if ('string' == typeof keys) keys = keys.split(/ +/);
  
  // 2
  return keys.reduce(function(ret, key){
    if (null == obj[key]) return ret;
    ret[key] = obj[key];
    return ret;
  }, {});
};

源码不是特别复杂。首先是将字符串属性转换为数组形式,如 const info = only(user, "email phone id job") 。再将属性数组用 reduce 迭代每一个属性,如果源对象中不存在当前迭代的属性,则继续迭代下一个属性。如果存在,就赋值给一个新对象,迭代结束后,把新对象作为结果返回。

测试用例

通过看测试用例,可以很快的学习一个 npm 包或开源库的使用,堪称文档中的战斗机。

var only = require('..');

var obj = {
  name: 'tobi',
  last: 'holowaychuk',
  email: 'tobi@learnboost.com',
  _id: '12345'
};

var expected = {
  name: 'tobi',
  last: 'holowaychuk',
  email: 'tobi@learnboost.com'
};

describe('only(obj, keys)', function(){
  describe('given an array', function(){
    it('should return only the whitelisted properties', function(){
      only(obj, ['name', 'email', 'last']).should.eql(expected);
    })
  })

  describe('given an string', function(){
    it('should return only the whitelisted properties', function(){
      only(obj, 'name email last').should.eql(expected);
    })
  })

  it('should omit undefineds', function(){
    only({}, 'foo bar baz').should.eql({});
  })
})