Javascript 将D3函数包装在对象中不会';不行。为什么?
如果我给一个变量分配一个d3.scale函数,我可以传入一个数字,它会正确地缩放这个数字 但是,如果我将同一个函数包装到一个对象中,它不会返回我期望的答案。为什么?Javascript 将D3函数包装在对象中不会';不行。为什么?,javascript,d3.js,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));
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 *
很明显,d3返回的函数在调用时保持某种状态。但是,当分配给
obj
由于未维护任何状态,因此无法计算适当的结果
如果您试图直接调用函数实例,这可能是一种更好的方法:
var obj = {
returnResult: d3.scale.ordinal()
.domain([0, 2])
.rangePoints([0, 1024])
}
这将允许您执行现在正在执行的操作,而无需每次重新创建对象。您使用的是有序比例,即具有离散域的比例。在您的例子中,这个离散域就是集合{0,2}。我不确定如果你输入一个不在1024集中的数字,行为会如何定义,但我相信d3没有定义这个 如果传入0或2,结果将与预期一致 本声明中还有一个问题:
return d3.scale.ordinal()
.domain([0, 2])
.rangePoints([0, 1024])
.call(n);
要调用的第一个参数是“thisArg”:
该块应改为:
return d3.scale.ordinal()
.domain([0, 2])
.rangePoints([0, 1024])
.call(null, n);
这里有一个难题:在JSFIDLE中找到的代码就是适合我的答案。谢谢你,卡尔!最后的工作解决方案是:
var obj={myScale:function(n){return d3.scale.ordinal().domain([0,2])。rangePoints([0,1024])。call(null,n);}}}console.log(obj.myScale(0));/返回0 console.log(obj.myScale(2));//返回1024个
感谢您的帮助@cesutherland在这里提出了一个适合我需要的解决方案: