由事件监听器绑定的函数如何继承' this '对象?

How do functions bound by event listeners inherit `this` object

本文关键字:继承 对象 this 绑定 监听器 事件 函数 何继承      更新时间:2023-09-26

只能使用纯Javascript。-我也很新手,所以很抱歉如果我的问题有点复杂。

我正在操作一个htmlCollection var puzzleAreaContents -其中包含16个<div>标签

接下来我们进入一个循环,循环遍历元素,并添加一个click事件侦听器。

puzzleAreaContents[movables[i]].addEventListener("click", shiftPuzzlePiece);

当我点击元素时,我可以在shiftPuzzlePiece函数中访问this,"这"是我刚刚点击的<div>标签。

我有两个问题

  1. shiftPuzzlePiece函数如何/为什么可以访问this,单击dom元素?
  2. 我怎么能传递任何任意元素到shiftPuzzlePiece而不破坏它目前的可用性?—我怎么能定义this当我传递一个对象的函数,使它的行为相同或类似于当它通过点击事件监听器调用?

也就是说它当前没有设置为接收参数

ex: shiftPuzzlePiece(some_arg)

  1. 事件处理程序创建一个新的执行上下文ECMA,它将此绑定到被单击的元素
  2. 您可以使用自己的绑定,以便将this替换为callMDN
例如,

shiftPuzzlePiece.call(puzzleAreaContents[movables[i]]);

您可以通过使用bind将任何值绑定为this对象。例如:

shiftPuzzlePiece.bind({x:23});

将确保this对象的this.x等于23

你也可以给其他参数pass,但是它们必须是有序的。Bind返回一个函数。

关于bind的更多信息请点击此处。

callapply函数的工作原理类似,但它们不返回一个新函数,而是调用该函数。

通常以语句/表达式的形式调用函数:

var ret = shiftPuzzlePiece(arg0);

还有Function.prototype.call和.apply,您可以使用它们提供this上下文:

var ret = shiftPuzzlePiece.call(that, arg0);
var ret = shiftPuzzlePiece.apply(that, [ arg0 ]);

现在that在函数内变成了this


例子
var piece = { };
puzzleAreaContents[movables[i]].addEventListener("click", function () {
    shiftPuzzlePiece.call(piece, this /* element */);
});
function shiftPuzzlePiece(element) {
   // this === piece
   // element === the clicked puzzleAreaContents
}

这里没有提到的另一种方法是使用closure,它实际上比apply(), call()bind()更快

(function f(){
  this.a = 0;
  var self = this;
  var e = document.getElementById('list').children, i;
  for (i = 0; i < e.length; i++) {
    (function(i){
      e[i].onclick = function(){
        _f(this, i);
      };
    })(i);
  }
})();

也可以这样写

(function f(){
  this.a = 0;
  var self = this;
  var e = document.getElementById('list').children, i;
  for (i = 0; i < e.length; i++) {
    e[i].onclick = (function(i){
      return function() {
        _f(this, i);
      };
    })(i);
  }
})();

最后是_f函数在这里是

function _f(y, z){
  console.log(this.a + " / " + y.innerHTML + " / " + z);
}
HTML

<ul id="list">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
</ul>
输出:

0 / 1 / 0
0 / 2 / 1
0 / 3 / 2
0 / 4 / 3
0 / 5 / 4

Working jsBin | benchmark