在对象内包装D3函数不起作用。为什么?

时间:2013-08-03 16:12:45

标签: javascript d3.js

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

2 个答案:

答案 0 :(得分: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/

答案 1 :(得分:0)

很明显,d3返回的函数在调用时保持某种状态。但是,每次在分配到obj

时调用它时,都会重新创建它

由于没有维持状态,因此无法计算出合适的结果。

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

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

这将允许您在不重新创建对象的情况下立即执行您正在执行的操作。