2

如果我将 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 *
4

2 回答 2

1

您正在使用序数尺度,它是具有离散域的尺度。在您的情况下,该离散域是集合 {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/

于 2013-08-03T16:56:45.163 回答
0

很明显,d3 返回的函数在调用它时会保持某种状态。但是,您每次调用它时都会重新创建它obj

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

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

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

这将允许您执行您现在正在执行的操作,而无需每次都重新创建对象。

于 2013-08-03T16:24:06.677 回答