理解d3.js源:卡在function.call()和“= +”

时间:2012-05-31 22:46:41

标签: javascript d3.js reverse-engineering force-layout

在d3.layout.force的源代码第158行中,有这段代码

force.charge = function(x) {
    if (!arguments.length) return charge;
    charge = typeof x === "function" ? x : +x;
    return force;
};

现在,如果你去第225行,你会看到

charges = [];
if (typeof charge === "function") {
  for (i = 0; i < n; ++i) {
    charges[i] = +charge.call(this, nodes[i], i);
  }
} else {
  for (i = 0; i < n; ++i) {
    charges[i] = charge;
  }
}

我在这里不明白的是

charges[i] = +charge.call(this, nodes[i], i);

我是JavaScript的新手,无法理解这里发生了什么。

据我所知,收费仅需1个参数(x)。这里传递“this”来给出当前对象的上下文但是其他两个呢? “nodes[i]”和“i”中的哪一个被视为“x”?

= +”在这里做什么呢?

3 个答案:

答案 0 :(得分:1)

查看callapplybind的MDN列表。

这是一个难以理解的概念,但是在调用和应用中发生的事情是你选择在不同的“上下文中”执行一个函数。

我说带有引号的“context”作为“执行上下文”在JS中有一个确切的含义,这不是它。我没有很好的说法,但这里发生的是你在执行函数时交换this对象。

这可能会有所帮助:

var obj = { foo: "bar" };
method.call( obj, "arg" );
function method( arg ) {
    console.log( this.foo ); #bar
    console.log( arg ); #"arg"
}

答案 1 :(得分:1)

我想你会找到答案here

基本上,它正在转换这个:

function(){ return +new Date; }

进入这个:

function(){ return Number(new Date); }

基本上,它将参数转换为数字,并将其添加到之前的值。

有关此here

的更多信息

答案 2 :(得分:0)

您必须更加谨慎地关注charge。它是line 11中的变量:

charge = -30,

您引用的功能force.charge用于设置费用,{strong> <{1}}中引用的功能 。看看+charge.call(this, nodes[i], i);的第二行:

force.charge

charge = typeof x === "function" ? x : +x; 可以是传递的函数(回调),以动态计算费用。当前节点(x)和节点索引(nodes[i])将传递给此回调,以便您可以根据以下值动态计算费用:

i

force.charge(function(node, index) { return index * 2; }); (因此x)也可以是数字或数字字符串。这就是事先测试charge是否为函数的原因:

charge

Apert,无论它定义了多少参数,您都可以随时将任意数量的参数传递给函数。例如:

if (typeof charge === "function") {
  // function so we call it and pass the current node and index
} else {
  // static value, the same for each node
}

会提醒function foo() { alert([].join.call(null, arguments)); } foo('a', 'b');


回答你的问题:传递给.call() [MDN].apply() [MDN]的参数以相同的顺序传递给函数。因此,如果我有一个函数a,b,那么function foo(a, b, c)foo.call(null, x, y)传递为xa传递为yb将是c)。

undefined运算符是unary plus operator [MDN],它只是将操作数转换为数字。