我现在正在使用d3(v3)的笔刷功能,遇到了构造函数中的绑定有效但使用类函数无效的情况。我的.babelrc
是为"presets": ["flow", "latest", "stage-2", "react"]
的类函数设置的,而我的其余代码中都使用了箭头函数,所以这与编译器无关。
有问题的代码:
this.brush = d3.svg.brush()
.x(xScale)
.on("brushend", this.changeDates)
const brushGroup = d3.select(this.node).append("g")
.attr("class", "brush")
.call(brush)
如果按如下方式在构造函数中绑定更改日期,则会发现函数this
中的changeDates
是React组件ExampleSVG
,这是所需的行为。
class ExampleSVG extends Component {
constructor(props) {
super(props)
this.changeDates = this.changeDates.bind(this)
}
changeDates() {
console.log(this) //ExampleSVG {props: {...}, context: {...}}
}
...d3 stuff
}
但是,如果我尝试通过箭头函数进行绑定,则this
会成为函数svg组。
class Example extends Component {
changeDates = () => {
console.log(this) //<g class="brush" ... />
}
...d3 stuff
}
为什么arrow函数没有绑定(再一次,不是翻译问题,我的代码中有很多绑定箭头)?我在这里可能缺少有关d3 / this的某些信息,但我想弄清楚!是call
吗?在这种情况下,call
可以做什么以使其可以覆盖箭头绑定?
答案 0 :(得分:3)
箭头功能没有自己的this
。
通过将非箭头函数传递给D3选择方法(例如.attr()
,.on()
),D3使用function.apply()将this
设置为要修改的元素,这就是为什么它不是窗口的原因(全局作用域this
;如果不是,则为this
,其作用域包括箭头功能)。
但是,由于箭头函数不能具有自己的作用域this
,因此this
指的是this
具有包含箭头函数的作用域的任何对象。
因此,this
的典型功能与箭头功能相比有所不同。因此,为什么不应该在要求您选择this
的d3选择方法中不使用粗箭头功能,除非您使用其他方法来选择该元素。
来自MDN:
在箭头函数中,
this
保留了封闭的词法上下文this的值。在全局代码中,它将被设置为全局对象...这同样适用于在其他函数内部创建的箭头函数:它们仍然属于封闭的词法上下文。
但是,您肯定可以保留箭头功能,并且仍然引用将为this
的元素,因为第二个参数是当前索引,第三个参数是所选内容中的元素数组。这个answer已经说过这种方法。