Давайте посмотрим, что 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
как элемент DOM, которым манипулируют, используя .apply
в функции, переданной в selection.attr()
, selection.on()
и т. Д. Однако он не делает этого для функций, вызываемых в функции, переданной в selection.attr()
, selection.on()
и т. Д.
Мы можем видеть, что this
действительно является элементом DOM, если мы регистрируем this
в функции, переданной selection.on()
. Если this
явно не установлено, это будет окно (если только не используется строгий режим, то оно будет неопределенным). Мы можем видеть во вложенной функции, this
действительно окно.
ответ Altocumulus и ответ Герардо полностью исключают проблему 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 применит к нему ожидаемое значение (это также по-прежнему дает доступ к данным и индексу, если необходимо):
В этом случае не ставьте скобки на функцию, мы не хотим возвращать результат функции, мы хотим использовать саму функцию.
Я использую apply (Function.prototype.apply()
) в моих примерах, но вы также можете использовать call (Function.prototype.call()
), как отмечает Altocumulus ниже . Использование вызова довольно похоже. Если вы не передаете в функцию какие-либо параметры и хотите сохранить только this
, использование будет таким же: someFunction.apply(this)
/ someFunction.call(this)
. Но, если передаются параметры, call не использует массив для параметров:
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>