【问题标题】:Understanding d3.js source: stuck at function.call() and "=+"了解 d3.js 源代码:卡在 function.call() 和“=+”
【发布时间】:2012-06-06 05:21:32
【问题描述】:

在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 新手,无法理解这里发生了什么。

据我了解,charge 只需要 1 个参数 (x)。这里传递了“this”来给出当前对象的上下文,但是另外两个呢? “nodes[i]”和“i”中的哪一个被视为“x”?

= +”又在这里做什么?

【问题讨论】:

  • 我认为还有另一个“充电”功能。

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


【解决方案1】:

查看 callapplybind 的 MDN 列表。

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

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

这可能会有所帮助:

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

【讨论】:

  • 非常感谢您的回答,但正如我提到的,我知道“this”是为了传递当前对象的上下文而给出的。我对 call、apply 和 bind 的工作原理一无所知,但我不明白其他两个参数(因为函数 charge 只接受一个参数)在那里做什么?
【解决方案2】:

我想你会找到答案here

基本上,它正在转换:

function(){ return +new Date; }

进入这个:

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

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

更多关于这个here的阅读

【讨论】:

  • 很高兴我能帮上忙!如果它回答了您的问题,请确保接受答案。 :)
【解决方案3】:

您必须更仔细地关注charge。它是line 11中定义的变量:

charge = -30,

你引用的函数force.charge设置收费的,它不是+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 是否为函数:

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');

将提醒a,b


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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多