作者:Soaring_Tiger 转载请注明出处 http://blog.youkuaiyun.com/Soaring_Tiger
前情提要1 : lodash中文学习拾零之Array篇
前情提要2:lodash 中文学习拾零之 Chain篇
前情提要3:lodash 中文学习拾零之 Collection篇
4. 处理哪些Object?
lodash的Object方法处理的是:function, array, string, JSON
4.1 判断Object类型
lodash提供了一系列用于判断Obejct类型的方法,称为 variadic functions:
_.isString
_.isArray
_.isTypedArray
_.isNumber
_.isBoolean
_.isDate
_.isPlainObject
_.isRegExp
_.isFunction
_.isObject
_.isPlainObject
_.isFinite
_.isElement
_.isNative
_.isUndefined
_.isNull
_.isNaN
//例如下面这个 _.isString用来判断输入的参数是否是String类型
function hello(name) {
if (_.isString(name)) {
return 'hello, ' + name;
}
}
hello('world');
// → "hello, world"
hello();
// → undefined
//判断是否是函数的参数
_.isArguments(function() { return arguments; }());
// → true
_.isArguments([1, 2, 3]);
// → false
//判断是否语言意义上的Object:
//(e.g. arrays, functions, objects, regexes, new Number(0), and new String(''))
_.isObject({});
// → true
_.isObject([1, 2, 3]);
// → true
_.isObject(1);
// → false
//判断是否 plain object
function Foo() {
this.a = 1;
}
_.isPlainObject(new Foo);
// → false
_.isPlainObject({a:1});
// → true
4.2 赋值与取值(Assigning and accessing properties)
创建一个javascript object对象并对之赋值是个常见工作,其中有些过程挺无聊的,比如:把一个对象的部分数据搞到另一个里去、或者必须确保为新对象填充默认值、确定是否存在某个key并且准确的赋值……
不用慌,对于上述等等无聊的事情,lodash提供了一系列工具来让你轻松完成。
4.2.1 扩展对象(Extending objects)
4.2.1.1 _.assign(object, [sources], [customizer], [thisArg])
注意[sources]这个参数,理论上可以是无限多,缺省情况下,后面的同名Key:Value对会覆盖前面的值。
的返回值一定是个Object
var object = {
name: '汤姆',
age: 42
};
_.assign(object, {occupation: '程序猿'},{'name':'杰瑞'});
//注意,此处新的 name:'杰瑞' 覆盖了原有的数据 '汤姆'
// →
// {
// name: "杰瑞",
// age: 42,
// occupation: "程序猿"
// }
// 设计自定义的回调函数
var defaults = _.partialRight(_.assign, function(value, other) {
return _.isUndefined(value) ? other : value;
});
defaults(object, { 'language': 'JS' }, { 'name': '果菲' });
// 原来没有的属性language及其值被添加了上去,而'name'的值还是保持不变
// → {
// 'name': '杰瑞',
// 'age': 42,
// 'occupation':'程序猿',
// 'language':'JS'
// }
4.2.1.2 _.merge(object, [sources], [customizer], [thisArg])
采用递归的方式将sources objects合并到目标Object当中,后面的相同属性会覆盖前面的相同属性。
_.merge (合并器)的
第一个参数是目标Object
第二个参数是源Object(即要合并进来的内容)
第三个参数是自定义处理器并接受五个参数(objectValue, sourceValue, key, object, source)
.merge的返回值一定是个Object
var users = {
'data': [{ 'user': '钱夫人' }, { 'user': '阿土伯' }]
};
var ages = {
'data': [{ 'age': 36 }, { 'age': 50 }]
};
_.merge(users, ages);
// → { 'data':
// [
// { 'user': '钱夫人', 'age': 36 },
// { 'user': '阿土伯', 'age': 50 }
// ]
// }
var object1 = {
states: { running: 'poweroff' },
names: [ 'CentOS', 'REHL' ]
},
object2 = {
states: { off: 'poweron' },
names: [ 'Ubuntu', 'Debian' ]
};
_.merge(object1, object2, function(a, b) {
if (_.isArray(a)) {
return a.concat(b);
}
});
// →
// {
// states: {
// running: "poweroff",
// off: "poweron"
// },
// names: [
// "CentOS",
// "REHL",
// "Ubuntu",
// "Debian"
// ]
// }
//注意下面的例子的差别:
_.merge({a:[20,30]},[1,2]);
//{"0":1,"1":2,"a":[20,30]}
_.merge([1,2],{a:[20,30]});
//[1,2]
扩展对象小结
.merge 与 .assign 的相似之处在于:都是把source object数据加到目标object中;
不同之处在于.assign 会直接将source object的property覆盖目标object,不会考虑差异; 而.merge则会比较两者的property细节,已存在的会被覆盖,新的则会添加上去。
4.2.2 缺省值
用于设定object缺省值
4.2.2.1 _.defaults(object, [sources])
目标Object中设定的值是缺省值,不能被sources的相同property覆盖
_.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' });
// → { 'user': 'barney', 'age': 36 }
_defaults([1,2],[3,4,5]);
// → [1,2,5]
4.2.2.2 _.defaultsDeep(object, [sources])
与defaults类似,但是用递归的方式分配默认值
_.defaultsDeep({ 'user': { 'name': 'barney' } }, { 'user': { 'name': 'fred', 'age': 36 } });
// → { 'user': { 'name': 'barney', 'age': 36 } }
4.3 查找keys和values
4.3.1_.findKey(object, [predicate=_.identity], [thisArg])
有点类型于Collection方法里的_.find,但是返回的是被匹配的Key的值(string|undefined)
var users = {
'barney': { 'age': 36, 'active': true },
'fred': { 'age': 40, 'active': false },
'pebbles': { 'age': 1, 'active': true }
};
_.findKey(users, function(chr) {
return chr.age < 40;
});
// → 'barney' (iteration order is not guaranteed)
// using the `_.matches` callback shorthand
_.findKey(users, { 'age': 1, 'active': true });
// → 'pebbles'
// using the `_.matchesProperty` callback shorthand
_.findKey(users, 'active', false);
// → 'fred'
// using the `_.property` callback shorthand
_.findKey(users, 'active');
// → 'barney' 注意这个值和上一个值的区别
//使用迭代器处理复杂查找的例子:
var object = {
Maria: [
'Python',
'Lisp',
'Go'
],
Douglas: [
'CSS',
'Clojure',
'Haskell'
]
};
var lang = 'Lisp';
//通过迭代器检查数据类型
_.findKey(object, function(value) {
if (_.isArray(value)) {
return _.contains(value, lang);
} else {
return value === lang;
} });
// → "Maria"
4.3.2_.findLastKey(object, [predicate=_.identity], [thisArg])
_.findLastKey查找的是最后一个符合条件的key
var users = {
'barney': { 'age': 36, 'active': true },
'fred': { 'age': 40, 'active': false },
'pebbles': { 'age': 1, 'active': true }
};
_.findLastKey(users, function(chr) {
return chr.age < 40;
});
// → returns `pebbles` 对比一下前面的例子 `_.findKey` 返回的是 `barney`
4.4 遍历对象(Iterating over objects)
4.4.1 基础遍历(Basic For Each)
4.4.1.1_.forOwn(object, [iteratee=_.identity], [thisArg])
实际上,当遍历的对象都是一个Object时,forOwn与Collection方法中的forEach的作用是完全相同的,因为它们都有共同的 base function
var object = {
name: 'Vince',
age: 42,
occupation: 'Architect'
}, result = [];
_.forOwn(object, function(value, key) {
result.push(key + ': ' + value);
});
// →
// [
// "name: Vince",
// "age: 42",
// "occupation: Architect"
// ]
function Foo() {
this.a = 1;
this.b = 2;
}
//下面的例子说明:(1)function也是object;(2)prototype不是"Own Key"
function Foo() {
this.a = 1;
this.b = 2;
}
Foo.prototype.c = 3;
_.forOwn(new Foo, function(value, key) {
console.log(key);
});
// → logs 'a' and 'b' (iteration order is not guaranteed)
4.4.1.2_.forOwnRight(object, [iteratee=_.identity], [thisArg])
遍历方向与forOwn相反。
4.4.2 搜索继承属性 Including inherited properties
_.forOwn无法检索继承下来的属性,所以要检索继承的属性就要用 forIn和 forInRight了。
4.4.2.1_.forIn(object, [iteratee=_.identity], [thisArg])
function Foo() {
this.a = 1;
this.b = 2;
}
Foo.prototype.c = 3;
_.forIn(new Foo, function(value, key) {
console.log(key);
});
// → logs 'a', 'b', and 'c'
4.4.2.2_.forInRight(object, [iteratee=_.identity], [thisArg])
与_.forIn的次序相反
4.5 Keys和Values
4.5.1 Keys
4.5.1.1 _.keys(object)
获得object的所有own key,返回值为数组
function Foo() {
this.a = 1;
this.b = 2;
}
Foo.prototype.c = 3;
_.keys(new Foo);
// → ['a', 'b'] (prototype.c 没有被包含在内)
_.keys('hi');
// → ['0', '1'] (string被当成数组,0和1就是'h'和'i'的key)
4.5.1.2 _.keysIn(object)
获得object的所有key,prototype也包含在内
4.5.2 Values
4.5.2.1 _.values(object)
获得Object所有的own key的值
function Foo() {
this.a = 1;
this.b = 2;
}
Foo.prototype.c = 3;
_.values(new Foo);
// → [1, 2]
_.values('hi');
// → ['h', 'i']
4.5.2.2 _.valuesIn(object)
获得Object所有Key的值,prototype的值也包括在内。
function Foo() {
this.a = 1;
this.b = 2;
}
Foo.prototype.c = 3;
_.valuesIn(new Foo);
// → [1, 2, 3] (iteration order is not guaranteed)
4.6 调用方法
4.6.1_.result(object, path, [defaultValue])
第一个参数是Object,第二个参数是被调用的方法(或属性)的路径,第三个参数是缺省值
var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
_.result(object, 'a[0].b.c1');
// → 3
_.result(object, 'a[0].b.c2');
// → 4
_.result(object, 'a.b.c', 'default');
// → 'default'
_.result(object, 'a.b.c', _.constant('default'));
// → 'default'
4.6.2 _.functions(object)
列出object的所有方法
function Person(first, last) {
this.first = first;
this.last = last;
}
Person.prototype.name = function() {
return this.first + ' ' + this.last;
};
_.functions(new Person('Teresa', 'Collins'));
// → [ "name" ]
4.7 转化对象(Transforming objects)
有时候,我们手上的对象并不能满足我们的需要,而要转成其他形式的数据结构,而lodash刚好提供了一批这样的工具。
4.7.1 _.pairs(object)
将对象转为数组
_.pairs({ 'barney': 36, 'fred': 40 });
// → [['barney', 36], ['fred', 40]]
4.7.2 _.pick(object, [predicate], [thisArg])
挑选对象的特定的property,并返回一个新的object
var object1 = {
name: 'Kevin Moore',
occupation: 'Programmer'
},
object2 = {
specialty: 'Python',
employer: 'Acme'
};
_.assign(object1, _.pick(object2, 'specialty'));
// →
// {
// name: "Kevin Moore",
// occupation: "Programmer",
// specialty: "Python"
// }
4.7.3 _.omit(object, [predicate], [thisArg])
扔掉指定的property,返回一个新的Object
var object1 = {
name: 'Kevin Moore',
occupation: 'Programmer'
},
object2 = {
specialty: 'Python',
employer: 'Acme'
};
_.assign(object1, _.omit(object2, 'employer'));
// →
// {
// name: "Kevin Moore",
// occupation: "Programmer",
// specialty: "Python"
// }
var object = { 'user': 'fred', 'age': 40 };
_.omit(object, 'age');
// → { 'user': 'fred' }
_.omit(object, _.isNumber);
// → { 'user': 'fred' }
4.7.4 _.invert(object, [multiValue])
颠倒key和value,第二个参数为是否接受多个值
var object = { 'a': 1, 'b': 2, 'c': 1 };
_.invert(object);
// → { '1': 'c', '2': 'b' }
// with `multiValue`
_.invert(object, true);
// → { '1': ['a', 'c'], '2': ['b'] }
4.8 创建和克隆对象
4.8.1_.create(prototype, [properties])
创建对象
function Shape() {
this.x = 0;
this.y = 0;
}
function Circle() {
Shape.call(this);
}
Circle.prototype = _.create(Shape.prototype, {
'constructor': Circle
});
var circle = new Circle;
circle instanceof Circle;
// → true
circle instanceof Shape;
// → true
4.8.2 _.clone(value, [isDeep], [customizer], [thisArg])
克隆对象
function Person(first, last) {
this.first = first;
this.last = last;
}
var object1 = {
first: 'Laura',
last: 'Gray'
},
object2 = new Person('Bruce', 'Price'),
clone1 = _.clone(object1),
clone2 = _.clone(object2);
clone1.first === 'Laura';
// → true
clone2.first === 'Bruce' && clone2 instanceof Person;
// → false
4.8.3 _.cloneDeep(value, [customizer], [thisArg])
深度克隆
var users = [
{ 'user': 'barney' },
{ 'user': 'fred' }
];
var deep = _.cloneDeep(users);
deep[0] === users[0];
// → false
// using a customizer callback
var el = _.cloneDeep(document.body, function(value) {
if (_.isElement(value)) {
return value.cloneNode(true);
}
});
el === document.body
// → false
el.nodeName
// → BODY
el.childNodes.length;
// → 20