我尝试使用以下代码在按钮数组上注册回调。但我似乎无法理解如何绑定(bind)回调中所需的字符串。任何建议将不胜感激!
for (var i = 0; i < this.car_types.length; ++i) {
this.select_car_buttons.push($("#button_select_car_" +
this.car_types[i].car_type));
this.select_car_buttons[this.select_car_buttons.length - 1]
.click(function() {
console.log(this.car_types[i].car_type);
}.bind(this));
}
不知何故,this
对象是按钮本身,而不是在其范围内调用函数的对象。
编辑:看起来这个对象确实被正确地传递了。问题是变量 i
没有超出范围,并且是通过引用而不是值捕获的。我应该如何解决这个问题?
此外,JavaScript 作为一种语言似乎存在很多此类问题(至少考虑到传统 C 家族语言(例如 C 和 C++)所采用的语义是正确的,这些问题可以归类为问题),是否有一些问题我可以阅读警告我注意此类问题的文章吗?
另一个编辑:在尝试使用值捕获的i
值进行闭包时,我尝试了以下代码
this.select_car_buttons[this.select_car_buttons.length - 1]
.click((function(scoped_i) {
return function() {
console.log(this.car_types[scoped_i].car_type);
}.bind(this);
}(i)));
但是我在 Safari 中收到以下错误
TypeError: undefined is not an object (evaluating 'scoped_i')
编辑:相同的代码可以在 Firefox 和 Chrome 中运行,但不能在 Safari 中运行!
最佳答案
这是一个范围问题。对于现代浏览器(支持 ES6),您只需在 for
循环中将 var
更改为 let
即可修复。
for (let i = 0; i < this.car_types.length; ++i)
引用MDN docs
The let statement declares a block scope local variable, optionally initializing it to a value.
要获得更多全局支持(非 ES6 支持),请使用立即调用的函数为变量创建额外的范围(您将其作为参数传递)
this.select_car_buttons[this.select_car_buttons.length - 1]
.click((function(scoped_i) { // IIF starts here, the new variable is called scoped_i for verbosity
return function() { // your original function code goes here
console.log(this.car_types[scoped_i].car_type); // use the newly scoped variable
}.bind(this);
}.bind(this)(i))); // end and execute the IIF while passing the i variable to it
关于javascript - 如何摆脱 JavaScript 中的绑定(bind)情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36524222/