白名单

有时候,我们只需要一个对象的部分属性,即丢弃到该对象部分属性,例如,在一个 server 程序中,我们最终发到后端的请求包会过滤掉一些他不需要的参数。在 underscore 中,就通过 _.pick 方法来达到这一目的。

_.pick(obj, whitelist)

_.pick(obj, whitelist):跟据白名单 whitelist,选出 obj 中的属性

_.pick 方法不是原地的,他将会返回一个新对象,而不是直接在 obj 上直接过滤属性。白名单 whitelist 既支持传递参数序列(keys),也支持传递一个函数来做过滤规则

源码

_.pick = restArgs(function (obj, keys) {
    var result = {}, iteratee = keys[0];
    if (obj == null) return result;
    // 白名单机制最终都会落脚到一个真值检验函数上,无论第二个参数是一个函数还是一个个的keys
    if (_.isFunction(iteratee)) {
        if (keys.length > 1) iteratee = optimizeCb(iteratee, keys[1]);
        keys = _.allKeys(obj);
    } else {
        // 如果第二个参数是一系列的key,则暗示pick的条件根据key是否在obj中进行pick
        iteratee = keyInObj;
        // 将keys展平
        keys = flatten(keys, false, false);
        // 对象化`obj`,保证后续操作顺利进行
        obj = Object(obj);
    }
    // 开始pick
    for (var i = 0, length = keys.length; i < length; i++) {
        var key = keys[i];
        var value = obj[key];
        if (iteratee(value, key, obj)) result[key] = value;
    }
    return result;
});

用例

var student = {
    name: 'wxj',
    age: 13,
    family: {
        son: 'lcx'
    },
    hobby: 'soccer'
};
var student2 = _.pick(student, 'name', 'age');
var student3 = _.pick(student, function(value, key, obj){return key === 'age';})
// =>
// student2: {
//     name: 'wxj',
//     age: 13
// },
// student3: {
//     age: 13
// }

_.omit(obj, blacklist)

_.omit(obj, blacklist):与 _.pick 相反,过滤掉黑名单 blacklist 中的属性

_.omit 的实现很容易,就是通过 _.negate 对传入的白名单函数取反(构成了黑名单函数),再执行 _.pick,再次体现了 underscore 中高度的函数复用:

// 1.8.3
_.omit = function(obj, iteratee, context) {
  if (_.isFunction(iteratee)) {
    iteratee = _.negate(iteratee);
  } else {
    var keys = _.map(flatten(arguments, false, false, 1), String);
    iteratee = function(value, key) {
      return !_.contains(keys, key);
    };
  }
  return _.pick(obj, iteratee, context);
};

// master
_.omit = restArgs(function (obj, keys) {
    // 可以看到,_.omit的实现基于_.pick
    var iteratee = keys[0], context;
    if (_.isFunction(iteratee)) {
        iteratee = _.negate(iteratee);
        // 如果传入了条件函数,那么取下一个参数为执行上下文
        if (keys.length > 1) context = keys[1];
    } else {
        keys = _.map(flatten(keys, false, false), String);
        iteratee = function (value, key) {
            return !_.contains(keys, key);
        };
    }
    return _.pick(obj, iteratee, context);
});

用例

var student = {
    name: 'wxj',
    age: 13,
    family: {
        son: 'lcx'
    },
    hobby: 'soccer'
};
var student2 = _.pick(student, 'family', 'hobby');
// =>
// student2: {
//     name: 'wxj',
//     age: 13
// },

results matching ""

    No results matching ""