addEventListener、箭头函数和`this` [重复]

Posted

技术标签:

【中文标题】addEventListener、箭头函数和`this` [重复]【英文标题】:addEventListener, arrow functions, and `this` [duplicate] 【发布时间】:2017-06-14 08:27:27 【问题描述】:

我正在经历 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,我不明白为什么。

在这种情况下是否没有“正确”的方式将函数绑定到元素?

【问题讨论】:

如果你想使用this那么你需要使用常规函数。箭头函数不能真正与 this 一起正常工作。 另外,有没有正确的方法来使用箭头函数呢? 没有 我想我记得读过一些东西说或建议,明确编写箭头函数是为了避免影响“this”。 普通函数和thise.currentTarget(不是e.target!!) 箭头函数只允许从定义它们的环境继承'this'的值,而不是它们被调用的上下文。演示代码使用常规函数,'this'引用调用它的环境。根据定义,箭头函数不可能做到这一点,因此为什么不能在需要使用“this”的任何地方使用它们。 【参考方案1】:

这是什么?

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.

【讨论】:

箭头函数没有this的概念。 this 在箭头函数内部是 this 在其包含的词法环境中的任何内容。 因此“我知道这是过于简单化了”。我认为当有人刚刚学习 JS 时尝试讨论词汇范围可能不是最好的教学方法。如果您正在阅读本文并想要更正确的解释:箭头函数不绑定 this 所以 this 只是指它在封闭词法范围中引用的任何内容。但是,如果他们刚刚将其绑定到封闭范围,这在功能上是相同的。 关键是你的整个答案可以替换为“箭头函数没有这个概念。箭头函数内部的 this 是它们包含的词法环境中的任何内容。不要使用箭头函数如果你需要绑定this的值。"可能还有一些对 ECMAScript 2015 语言规范的引用。 这无法解释为什么他对 .bind 的尝试不起作用 这绝对可以解释为什么他的绑定尝试不起作用“箭头函数没有 this 的概念。箭头函数内部的 this 是它们包含的词法环境中的 this 。不要如果需要绑定 this 的值,请使用箭头函数。"

以上是关于addEventListener、箭头函数和`this` [重复]的主要内容,如果未能解决你的问题,请参考以下文章

10th week task -3 Arrow function restore

vue箭头函数与普通函数

箭头函数为什么不能作为构造函数?

箭头函数为什么不能作为构造函数?

箭头函数中的this

removeEventListener取消事件监听的坑