lodash用法系列(2),处理对象

 

Lodash用来操作对象和集合,比Underscore拥有更多的功能和更好的性能。

官网:https://lodash.com/
引用:<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script>
安装:npm install lodash

首先通过npm安装lodash:
npm i --save lodash

在js文件中引用lodash:
var _ = require('lodash');

 

本系列包括:

 

lodash用法系列(1),数组集合操作
lodash用法系列(2),处理对象 
lodash用法系列(3),使用函数 
lodash用法系列(4),使用Map/Reduce转换  
lodash用法系列(5),链式 
lodash用法系列(6),函数种种 

 

■ 类型隐式转换

true == 1;//右边的1会根据左边的true进行隐式转换
true === 1; //不会隐式转换

 

■ 判断参数是否是对象

 

function hello(greeting, person){
    if(_.isPlainObject(greeting)){
        person = greeting;
        greeting = 'hi';
    }
    return greeting + person.name;
}

hello('hello',{name:''});
hello({name:''});

 

■ 判断计算结果

在Javascript中:

 

1/0;//Infinity
1+ '';//NaN

lodash中提供了isFinite, isNumber, isNaN方法。

 

var operand1 = 2/0
    operand2 = NaN,
    results = [];
    
_.forEach([operand1, operand2], function(op){
    if(_.isFinite(op)){
        results.push('结果无穷尽');
    } else {
        if(!_.isNumber(op) || _.isNaN(op)){
            results.push('结果不是数字');
        } else {
            results.push('结果不正确');
        }
    }
}); 

console.log(results);

 

■ 判断对象是否是函数

 

var _ = require('lodash');

var o = {
    a: function(){return 'hi'},
    b: []
};

//hi
console.log(_.isFunction(o.a) && o.a());

//false
console.log(_.isFunction(o.b) && o.b());

 

■ 给对象添加字段,相同字段值重写

 

var o = {
    name: '',
    age:22
};

_.assign(o, {occupation:''});

 

如果新添加的字段已经存在,会把该字段的值重写掉。

■ 给对象添加字段,合并字段值

如果新添加对象的字段存在,是否可以不把该字段的值重写掉呢?
--lodash提供了merge方法,有更加细粒度的控制。

 

var o1 = {
    states: {running: 'off'},
    names: ['a','b']
};

var o2 = {
    states: {off: 'on'},
    names: ['c','d']
};

var result = _.merge(o1, o2, function(dest, src){
    if(_.isArray(dest) && _.isArray(src)){
        return dest.concat(src);
    }
});

//{ states: { running: 'off', off: 'on' },names: [ 'a', 'b', 'c', 'd' ] }
console.log(result);

 

以上,o1和o2都有相同的字段,使用merge方法后会遍历o1与o2的所有字段,但可喜的是:如果o2和o1的字段相同,并没有进行简单的重写字段值,而是进行了合并。并且,还可以判断o1和o2的字段类型,如果是数组,就把两个数组concat。

■ 给对象添加字段,保持原来字段的值

 

var o = {
    name: 'a'
};

_.defaults(o, {
    name: 'b'
});

 

■ 根据对象的值寻找键,findKey方法接受匿名函数

 

var o = {
    name: 'a',
    age: 20
}

var result = _.findKey(o, function(value){
    return value === 'a';
});

//name
console.log(result);

 

又比如。

var obj = {
    a: ['x','y'],
    b: ['m','n']
};

var search = 'x';

var result = _.findKey(obj, function(value){
    if(_.isArray(value)){
        return _.contains(value, search);
    } else {
        return value === search;
    }
});

//a
console.log(result);

 

■ 根据对象的值寻找键,findkey方法接受对象

 

var obj = {
    a: {
        name: 'a',
        age:20
    },
    b: {
        description:''
    }
};

var result = _.findKey(obj, {name: 'a'});

//a
console.log(result);

 

■ 查询对象

 

var o = {
    1: {
        first:'',
        enabled:false
    },
    2: {
        first: '',
        enabled:true
    }
};

var result = _.find(o, 'enabled');
var result = _.where(o, {first: ''});

 

■ 遍历对象的字段

 

var o = {
    name: '',
    age:20,
    description:''
};

var result = [];

_.forOwn(o, function(value, key){
    result.push(key + ': ' + value);
});

console.log(result);

 

可见,forOwn方法与forEach方法的不同之处在于匿名函数的第二个参数是键,不是索引。

■ 遍历对象的字段,对象有父对象

 

unction Person(){
    this.full = function(){return this.first + ' ' + this.last;};
}

function Employee(first, last, occupation){
    this.first = first;
    this.last = last;
    this.occupation = occupation;
}

Employee.prototype = new Person();

var employee = new Employee('darren','ji','programmer'),
    resultOwn = [],
    resultIn = [];

_.forOwn(employee, function(value, key){
   resultOwn.push(key);
});

//[ 'first', 'last', 'occupation' ]
console.log(resultOwn);

_.forIn(employee, function(value, key){
   resultIn.push(key);
});

//[ 'first', 'last', 'occupation', 'full' ]
console.log(resultIn);

 

可见,forIn会遍历包括父对象的字段,forOwn只遍历当前对象的字段。

■ 获取对象的所有字段

 

var o1 = {
    occupation: '',
    last:'',
    first:''
};

var result1 = _.sortBy(_.keys(o1));

//[ 'first', 'last', 'occupation' ]
console.log(result1);

 


■ 获取对象的所有字段,然后据此获取字段值

 

var o2 = {
    occupation: 'manager',
    last: 'ji',
    first: 'darren'
};

//[ 'darren', 'ji', 'manager' ]
console.log(_.at(o2, _.sortBy(_.keys(o2))));

 

■ 获取对象的所有字段值

 

var o = {};
_.values(o);

 

■ 当不确定对象某个字段是否是函数或其它时使用result方法

 

var o1 = {name: 'a'},
    o2 = {name: function(){return 'b';}},
    o3 = {};

console.log(_.result(o1,'name','darren'));//a
console.log(_.result(o2, 'name','darren'));//b
console.log(_.result(o3, 'name', 'darren'));//darren

 

■ 获取一个对象的所有方法名

 

function Person(first, last){
    this.first = first;
    this.last = last;
}

Person.prototype.name = function(){
    return this.first + ' ' + this.last;
}

//[ 'name' ]
var result = _.functions(new Person('darren','ji'));
console.log(result);

 

■ 把对象的键值对转换成数组元素

 

function format(label, value){
    return label + ': ' + value;
}

var o = {
    first: 'darren',
    last: 'ji',
    age:33
},result = '';

var pairsResult = _.pairs(o);

//[ [ 'first', 'darren' ], [ 'last', 'ji' ], [ 'age', 33 ] ]
console.log(pairsResult);

_.forEach(pairsResult, function(item){
    result += format.apply(null, item) + '\n';
});

//first: darren
//last: ji
//age: 33
console.log(result);

 

■ 选择对象中的某些字段

 

var o1 = {
    name: 'a',
    occupation:'b'
},
o2 = {
    spcecialty: 'c',
    employer: 'd'
};

//pick对象的字段
var o2pick = _.pick(o2, 'spcecialty');
//{ spcecialty: 'c' }
console.log(o2pick);

var result = _.assign(o1, o2pick);
//{ name: 'a', occupation: 'b', spcecialty: 'c' }
console.log(result);


■ 去除对象中的某些字段

 

_.omit(o2, 'employer');

 

去除字段值为bool,o, null的字段。

 

var o = {
    name: 'a',
    age:0,
    occupation:null,
    enabled: true
};

var r = _.omit(o, function(value){
    return !(!_.isBoolean(value) && value);
});

//{ name: 'a' }
console.log(r);

 

■ 颠倒对象的键和值

 

unction sortValues(object){
    return _.values(object).sort();
}

var o1 = {
    first: 'a',
    last: 'b'
},
o2 = {
    first: 'c',
    last: 'd'
};

//[ 'a', 'b' ]
console.log(sortValues(o1));

[ 'first', 'last' ]
console.log(sortValues(_.invert(o2)));

 

■ 创建对象

 

unction Person() {
}

Person.prototype.name = function () {
    return this.first + ' ' + this.last;
}

var arr = [
    {first: 'aa', last: 'bb'},
    {first: 'cc', last: 'dd'},
    {first: 'ee', last: 'ff'},
],
    people = [];

_.forEach(arr, function(item){
   people.push(_.create(Person.prototype, item));
});

//[ 'aa bb', 'cc dd', 'ee ff' ]
console.log(_.invoke(people, 'name'));

 

以上,可以吧Person看作是一个接口或抽象类,通过prototype属性动态添加name方法。通过create方法动态把实例和Person.prototype绑定上。最后,通过invoke方法触发数组内Person元素的name方法。

■ 拷贝对象

 

function Person(first, last){
    this.first = first;
    this.last = last;
}

var o1 = {
    first: 'darren',
    last: 'ji'
},
o2 = new Person('jack','chen'),
clone1 = _.clone(o1),
clone2 = _.clone(o2);

//darren
console.log(clone1.first);

//jack
console.log(clone2.first);

 

参考资料:lodash in essential

 

未完待续~~

 

posted @ 2015-12-01 21:29  Darren Ji  阅读(33083)  评论(0编辑  收藏  举报

我的公众号:新语新世界,欢迎关注。