我正在改变这个对象数组:
[
{
first: {
blah: 1,
baz: 2
}
},
{
second: {
foo: 1,
bar: 2
}
}
]
对于这个更简单,扁平的物体:
{
first: {
blah: 1,
baz: 2
},
second: {
foo: 1,
bar: 2
}
}
我发现使用Underscore / LoDash执行此操作的两种最简单的方法是:
// Using reduce and extend
_.reduce(myArray, _.extend)
// Using assign and apply
_.assign.apply(_, myArray);
完整的代码记录在JSBin:http://jsbin.com/kovuhu/1/edit?js,console
中我已经阅读了很多关于apply / bind / call / assign / reduce / extend的文档...但是我无法理解窗帘背后的实际情况。
有人可以帮助我理解这些单线演奏的魔术技巧的秘诀吗?
答案 0 :(得分:4)
要理解这一点,让我们做一个简单的assign(版本扩展)版本。我们只接受一个参数,我们将其称为source,我们将其添加到结果中。
function assign(result, source) {
var keys = Object.keys(source),
length = keys.length;
for (var i=0 ; i < length; i ++) {
var key = keys[i];
result[key] = source[key];
}
return result;
}
现在让我们把输入分成几部分:
var a = {
first: {
blah: 1,
baz: 2
}
}
var b = {
second: {
foo: 1,
bar: 2
}
}
var input = [a, b];
现在我们可以调用reduce:
_.reduce(input, assign);
reduce将调用assign两次:
assign(result, a);
// assigns the (key, value) pair ("first", {blah: 1, baz: 2}) to result
assign(result, b);
// assigns the (key, value) pair ("second", {foo: 1, bar: 2}) to result
谈话很便宜,告诉我代码: http://jsbin.com/hexiza/3/edit?js,console
您可以在Lo-Dash source code中看到如何使用createAssigner()和baseAssign()实现assign。
答案 1 :(得分:2)
reduce
获取对象中数组/属性中的所有值,并aggregates them。在这种情况下,extend
会传递给reduce
,这意味着您传递的function(a,b)
用于扩展值a
(在每一步中继续执行)以及所有属性object b
(数组中的每个值,一次一个)。在你的单行代码中,下划线的reduce
遍历数组,从对象{}开始,并简单地将所有数组元素属性转储到该对象中,因为它沿着输入数组行进。在简单的JS中,它将类似于:
var thing = {};
var deeparray = [{...}, {...}, {...}];
deeparray.forEach(function(v) {
Object.keys(v).forEach(function(k) {
thing[k] = v[k];
}
});
return thing;
assign
(not found in underscore)做同样的事情,拿出一系列对象并将它们压在一起。这实际上是它唯一做的事情。调用_assign.apply(_, myArray)
与_调用this.assign(myArray)
相同 - apply
是用于调用函数的基本JavaScript函数,而#34;手动覆盖&#34;关键字this
在该函数中的含义。 _.assign.apply(_,myArray)
与调用_.assing(myArray)
相同,除了this
将是lodash的附加保证,而不是一些随机函数作用域上下文。