让我们看看this 对您的每种方法的定义:
// console.log(this) in inline function:
<svg width="960" height="960">
// console.log(this) in function called from inline function:
Window → file:///fileName.html
this 由函数的调用方式设置。 D3 方便地将this 设置为通过在传递给selection.attr()、selection.on() 等的函数上使用.apply 来操作的DOM 元素。但是,它不会对传递给@987654331 的函数中调用的函数执行此操作@、selection.on()等
如果我们在传递给selection.on()的函数中记录this,我们可以看到this确实是DOM元素。如果this 没有显式设置,它将是窗口(除非使用严格模式,否则它将是未定义的)。我们可以在嵌套函数中看到,this确实是窗口。
Altocumulus 的 answer 和 Gerardo 的 answer 完全避免了 this 的问题,此外,您还可以将 this 作为一些常规参数传递给函数(这种模式在一些示例中可见)。但是,如果您希望能够简单地将代码从内联函数复制并粘贴到某个单独定义的函数中,您可以使用 apply,它将保留 this 作为被修改的元素:
d3.select("body")
.append("svg")
.attr("width", 960)
.attr("height", 960)
.on('mousemove', function() {
var mouse = d3.mouse(this);
console.log("inline: ", mouse[0]);
someFunction.apply(this);
});
function someFunction() {
var mouse = d3.mouse(this);
console.log("not inline: ", mouse[0]);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
如果您需要同时将参数传递给您的函数,您仍然可以使用 apply:
someFunction.apply(this,[parameterA,parameterB,...]);
function someFunction(parameterA,parameterB) { }
d3.select("body")
.append("svg")
.attr("width", 960)
.attr("height", 960)
.on('mousemove', function() {
var mouse = d3.mouse(this);
console.log("inline: ", mouse[0]);
someFunction.apply(this,[mouse[0],mouse[1]]);
});
function someFunction(x,y) {
var mouse = d3.mouse(this);
console.log("not inline: ", mouse[0],x,y);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
但是,这个调用其他函数的内联函数可能只是额外的工作。如果您仅调用内联函数中的函数,则只需将被调用函数直接传递给selection.on(),这会保留this,而无需任何额外步骤,因为d3会将预期值应用于它(如果需要,它还可以让您访问数据和索引):
d3.select("body")
.append("svg")
.attr("width", 960)
.attr("height", 960)
.on('mousemove', someFunction)
function someFunction() {
var mouse = d3.mouse(this);
console.log(mouse[0]);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
这种情况下不要把括号放在函数上,我们不想返回函数的结果,我们要使用函数本身。
我在示例中使用了 apply (Function.prototype.apply()),但您也可以使用 call (Function.prototype.call()),正如 Altocumulus 注释 below。 call 的使用非常相似。如果您不向函数传递任何参数而只想保留this,则用法相同:someFunction.apply(this) / someFunction.call(this)。但是,如果传递参数,调用不会使用数组作为参数:
d3.select("body")
.append("svg")
.attr("width", 960)
.attr("height", 960)
.on('mousemove', function() {
var mouse = d3.mouse(this);
someFunction.call(this,mouse[0],mouse[1]); // first parameter will be `this` for someFunction, rest of parameters follow
});
function someFunction(x,y) {
var mouse = d3.mouse(this);
console.log(mouse[0],x,y);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>