在 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