在 JavaScript 中使用回调和闭包时维护对 "this" 的引用

在 JavaScript 编程中,我们经常使用回调和闭包来处理异步操作和函数嵌套。然而,在处理这些代码时,很容易遇到一个问题:如何正确地维护对 this 的引用。

问题背景

由于 JavaScript 是一种动态语言,函数的 this 关键字的指向会根据函数是如何被调用进行动态变化。例如:

----- ----- - -
  ----- -------
  ------- -
    ------------------- ---------------
  -
-

------------- -- -- ------- ------

----- ------- - -----------
--------- -- ---------- ------ ---- -------- ------ -- ---------

在上面的例子中,当我们直接调用 myObj.greet() 时,this 指向了 myObj 对象本身,因此可以正常输出 "Hello, John!"。但是,当我们将 myObj.greet 函数赋值给一个变量 greetFn 后,再次调用 greetFn() 时,this 已经不再指向 myObj,而是变成了全局对象 window(或者 undefined)。因此,代码会抛出 TypeError 异常。

同样的问题也会出现在回调和闭包中。例如:

----- ----- - -
  ----- -------
  ------------ -
    --------------------- -
      ---------------- ---------------
    -- -----
  -
-

------------------ -- -- ---- -----------

在上面的例子中,我们定义了一个名为 sayHiLater 的方法。该方法使用 setTimeout 来延迟 1 秒钟后执行一个函数。该函数尝试输出 this.name,但由于在回调函数内部 this 已经不再指向 myObj,而是变成了 window(或者 undefined),导致代码输出 "Hi, undefined!" 而不是 "Hi, John!"。

解决方案

为了解决这个问题,我们需要采用一些技巧来维护对 this 的引用。下面介绍两种常见的方法。

使用箭头函数

箭头函数是 ES6 中新增的语法,它的出现正好解决了 this 关键字的指向问题。箭头函数中的 this 始终指向其外层作用域中的 this。因此,如果我们在回调或闭包中使用箭头函数,就可以轻松地维护对 this 的引用。

例如:

----- ----- - -
  ----- -------
  ------------ -
    ------------- -- -
      ---------------- ---------------
    -- -----
  -
-

------------------ -- -- ---- ------

在上面的例子中,我们将 setTimeout 的回调函数改为箭头函数。因为箭头函数中的 this 指向外层作用域中的 this,因此在箭头函数内部可以正常访问到 myObj 对象中的 name 属性。

使用 bind 方法

除了箭头函数之外,我们还可以使用 Function.prototype.bind 方法来维护对 this 的引用。该方法会创建一个新的函数,其 this 关键字会被绑定到指定的对象上。

例如:

----- ----- - -
  ----- -------
  ------------ -
    --------------------- -
      ---------------- ---------------
    ------------- -----
  -
-

------------------ -- -- ---- ------

在上面的例子中,我们将 setTimeout 的回调函数使用 bind 方法

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/26877