addEventListener,箭头函数和`this`

时间:2017-01-28 20:39:43

标签: javascript this

我正在经历JavaScript30挑战,并且在lesson 3中他有一些事件监听器调用一个函数来引用它被称为this的元素:

const inputs = document.querySelectorAll('.controls input');
function handleUpdate() {
  const suffix = this.dataset.sizing || '';
  document.documentElement.style.setProperty(`--${this.name}`, this.value + suffix);
}
inputs.forEach(input => input.addEventListener('change', handleUpdate));
inputs.forEach(input => input.addEventListener('mousemove', handleUpdate));

我尝试使用ES6箭头功能重写它,但我无法让this正常工作。我使用target

进行了解决方法
const handleUpdate = (e) => {
  const that = e.target;
  const newValue = `${that.value}${that.dataset.sizing || ''}`;
  etc.
}

但我首先尝试绑定这样的函数:

input.addEventListener('change', handleUpdate.bind(this));

但函数内的this仍然指向window,我不明白为什么。

没有"对"在这种情况下将函数绑定到元素的方法?

1 个答案:

答案 0 :(得分:4)

这是什么?

this是Javascript中的一个特殊关键字,它指的是函数的执行环境:

  • 如果在全局范围内执行某个函数,this将绑定到窗口
  • 如果将函数传递给事件处理程序的回调函数,this将绑定到引发事件的DOM元素

结合

bind方法基本上说,当你调用函数时,用我的参数替换它。所以,例如:

let a = {}
function test_this() {
     return this === a;
}  

test_this(); // false
test_this.bind(a)(); // true (.bind() returns the bound function so we need to call the bound function to see the result)

此外,箭头函数只是用于将函数this绑定到当前值this的语法糖。例如,

let b = () => { /* stuff */ }

相同
let b = (function () { /* stuff */}).bind(this);

(基本上,我知道这是一种过度紧张的行为)

你的困境

在正常的事件过程中(不使用箭头函数),this绑定到DOM元素。

当您执行事件处理程序input.addEventListener('change', handleUpdate.bind(this));的创建时,您正在全局范围内运行(所以this === window)。所以你有效地运行input.addEventListener('change', handleUpdate.bind(window));(这是你注意到的行为)。使用箭头功能是一回事。

如果你想用匿名函数替换回调,你应该这样做:

const handleUpdate = function (e) {
  const that = e.target;
  const newValue = `${that.value}${that.dataset.sizing || ''}`;
  // etc.
}