下划线:平面对象的对象数组。什么是魔术?

时间:2014-11-11 01:32:57

标签: javascript underscore.js lodash

我正在改变这个对象数组:

[
  {
    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的文档...但是我无法理解窗帘背后的实际情况。

有人可以帮助我理解这些单线演奏的魔术技巧的秘诀吗?

2 个答案:

答案 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;

assignnot found in underscore)做同样的事情,拿出一系列对象并将它们压在一起。这实际上是它唯一做的事情。调用_assign.apply(_, myArray)与_调用this.assign(myArray)相同 - apply是用于调用函数的基本JavaScript函数,而#34;手动覆盖&#34;关键字this在该函数中的含义。 _.assign.apply(_,myArray)与调用_.assing(myArray)相同,除了this将是lodash的附加保证,而不是一些随机函数作用域上下文。