将D3函数封装在对象内部;不起作用.为什么?

Wrapping D3 functions inside objects doesn't work. Why?

本文关键字:不起作用 为什么 内部 对象 D3 函数 封装      更新时间:2023-09-26

如果我将d3.scale函数分配给一个变量,我可以传递一个数字,它将正确地缩放该数字。

然而,如果我把同一个函数包装在一个对象中,它不会返回我期望的答案。为什么?

var applyScale1 = d3.scale.ordinal()
    .domain([0, 2])
    .rangePoints([0, 1024]);
console.log(typeof(applyScale1));     // "function"
console.log(applyScale1(1));          // 0
console.log(applyScale1(5000));       // 1024 *Correct*
// But wrapping that in an object doesn't work. Why?
var obj = {
  returnResult: function(n) {
    var fn = d3.scale.ordinal()
      .domain([0, 2])
      .rangePoints([0, 1024]);
    return fn(n);
  },
  returnFunction: function() {
    return d3.scale.ordinal()
      .domain([0, 2])
      .rangePoints([0, 1024]);
  },
  withCall: function(n) {
    var fn = d3.scale.ordinal()
      .domain([0, 2])
      .rangePoints([0, 1024]);
    var nScaled = fn.call(n);
    return nScaled;
  },
  applySelf: function(n) {
    var self = this;
    var fn = d3.scale.ordinal()
      .domain([0, 2])
      .rangePoints([0, 1024]);
    var nScaled = fn.apply(self, [n]);
    return nScaled;
  },
  usingCall: function(n) {
    return d3.scale.ordinal()
      .domain([0, 2])
      .rangePoints([0, 1024])
      .call(n);
  },
};
console.log(obj.returnResult(1));         // = 0
console.log(obj.returnResult(5000));      // = 0 * Wrong *
console.log(obj.returnFunction()(1));     // = 0
console.log(obj.returnFunction()(5000));  // = 0 * Wrong *
console.log(obj.withCall(1));             // = 0
console.log(obj.withCall(5000));          // = 0 * Wrong *
console.log(obj.applySelf(1));            // = 0
console.log(obj.applySelf(5000));         // = 0 * Wrong *
console.log(obj.usingCall(1));            // = 0
console.log(obj.usingCall(5000));         // = 0 * Wrong *

您使用的是序数刻度,它是一个具有离散域的刻度。在您的情况下,该离散域是集合{0,2}。我不确定如果你输入一个不在1024集合中的数字,行为会如何定义,但我相信d3没有定义这个。

如果您输入0或2,结果将与预期的一样。

这份声明中还有一个问题:

return d3.scale.ordinal()
  .domain([0, 2])
  .rangePoints([0, 1024])
  .call(n);

要调用的第一个参数是"thisArg":https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call

该区块应为:

return d3.scale.ordinal()
  .domain([0, 2])
  .rangePoints([0, 1024])
  .call(null, n);

这是一把小提琴:http://jsfiddle.net/cesutherland/5gY6Z/2/

很明显,d3返回的函数在调用它时保持了某种状态。然而,当分配给obj 时,每次调用它都会重新创建它

因为没有维护任何状态,所以无法计算适当的结果。

如果您试图直接调用函数的实例,这可能是一种更好的方法:

var obj = {
   returnResult: d3.scale.ordinal()
      .domain([0, 2])
      .rangePoints([0, 1024])
}

这将允许你做你现在正在做的事情,而不需要每次都重新创建对象。