📜  JavaScript 中的箭头函数

📅  最后修改于: 2022-05-13 01:57:13.996000             🧑  作者: Mango

JavaScript 中的箭头函数

先决条件:JavaScript 中的 this

在这篇文章中,讨论了 JavaScript 中更多与this相关的函数。

this 和箭头函数:

ES6 中引入的箭头函数提供了一种在 JavaScript 中编写函数的简洁方法。
它提供的另一个显着优势是它不绑定自己的this 。换句话说,箭头函数内的上下文是词法或静态定义的。

我们的意思是什么?

与其他函数不同, this内部箭头函数的值不依赖于它们的调用方式或定义方式。它仅取决于其封闭上下文。
让我们试着用一个例子来理解:






      


输出:

[object Object] 
undefined is undefined years old

我们得到未定义的输出而不是正确的输出信息的原因是因为被定义为 setTimeout 回调的function()有一个正常的函数调用,正如我们所知,这意味着它的上下文被设置为全局上下文或其他单词this的值设置为 window 对象。

发生这种情况是因为每个常规的非箭头函数根据它们的调用定义了自己的this或上下文。封闭对象/函数的上下文不会影响这种自动定义自己的上下文的趋势。

我们如何解决这个问题?

想到的一个明显的解决方案是,如果函数没有定义自己的上下文怎么办?如果它从info()继承上下文怎么办,因为这意味着这个函数() 获得了在info()定义的this

嗯,这正是箭头功能do.They保留的价值this从他们的封闭
语境。
也就是说,在上面的例子中,如果定义为setTimeout()回调的函数是一个箭头函数,它将从它的封闭上下文中继承this的值 – info()




                    

  

输出:

[object Object] 
John is 21 years old

因此,无论是使用函数调用还是方法调用来调用箭头函数,它都会从其封闭上下文中保留this的 ] 值。换句话说,箭头函数的this值与其直接在其外部的值相同。



如果在任何封闭函数之外使用,箭头函数继承全局上下文,从而将this的值设置为全局对象。

这在单独的方法中:

当来自任何对象的方法与其分离或存储在变量中时,例如: let separated = People.info ,它会丢失对其调用对象的引用。

请注意info之后缺少左括号和右括号。这表明我们没有立即调用该方法。

例如 :




                    


输出:

[object Object] John is 21 years old
[object Window] undefined is undefined years old

一旦我们通过将info()person1对象存储在person1其从person1对象中separated ,我们就会丢失对person1对象的所有引用。
我们不能再通过在分离方法中使用this访问父对象,因为分离方法的上下文被重置为全局上下文。

因此,当我们调用separated()我们看到this现在被设置为全局窗口对象。

我们如何解决这个问题?
一种方法是在bind方法存储在separated时将对象的值与方法bind 。这确保了所有引用this指的是此绑定对象甚至在分离的方法。
这可以使用bind()来完成,如下所示:




                    


输出:

[object Object] John is 21 years old
[object Object] John is 21 years old

注意:我们可以使用任何对象将bind()到方法info() ,而不是 code.person1,并且输出会相应地改变。将方法绑定到它的父对象不是强制性的。



如果你已经走到这一步,你会注意到我们提到了bind()几次。
现在让我们研究一下什么是bind(), call() and apply()

绑定、调用和应用

bind()、call() 和 apply() 都用于修改函数的上下文。所有这三个都有助于明确指定函数内this的值。
但是,它们各自的工作方式存在某些差异。让我们研究这些差异。

绑定()

bind() 允许我们通过将对象绑定到该函数来显式定义this在函数内将具有的值。
绑定对象用作它绑定到的函数的上下文( this值)。
要使用它,我们主要需要两个东西——一个绑定到函数的对象和一个绑定这个对象的函数。

绑定的一般语法是:

boundfunction = someFunction.bind(someObject, additionalParams);

bind() 指令中使用的第一个参数用作this值,它后面的参数是可选的,用作绑定函数的参数。




                    


输出:

Orange is orange
Banana is Yellow

请注意,我们使用方法调用: fruit1.displayInfo在fruit1 上调用displayInfo(),因此可能期望它具有fruit1的上下文。然而,情况似乎并非如此,因为“香蕉是黄色”而不是“橙色是橙色”被记录下来。

发生这种情况是因为我们使用bind()命令将 displayInfo() 中this的值显式绑定到bindingObj
正如我们所见,将对象显式绑定到函数会覆盖其正常的上下文规则,并将所有this值强制设置为其中的绑定对象。

通常,在传递函数时,它会丢失上下文。例如:




                 

                                                         

输出:



[object Window] undefined

为了防止在作为回调传递的函数内部重置上下文,我们明确地将this的值绑定到与passAround()内部相同的值,即: bindingbinding对象:




                    

                                                        

输出:

[object Object] John

调用()和应用()

call() and apply()通过显式指定this应该存储在函数的值来执行类似于 bind 的任务。
然而,它们与bind()之间的一个主要区别是call() and apply()立即调用函数,而不是简单地准备一份带有this值的函数副本以备将来使用。

语法:
打电话

function.call(thisValue, arg1, arg2, ...)

申请

function.apply(thisValue, [ arg1, arg2, ...])

这两种情况下的第一个参数是我们希望被调用函数具有的this值。

本质上,这两种方法之间的唯一区别在于,在apply ,第二个参数是一个参数数组对象,而在call ,所有参数都以逗号分隔的格式发送。

例如:




                    

                                                       

输出:

[object Object] Banana is yummy
[object Object] Orange is sour

注意call()apply()都是默认函数对象原型上可用的方法。

这与事件侦听器

在用作事件侦听器回调的函数内部, this保存触发事件的元素的值。




如果这里使用的回调函数是一个箭头函数并且我们的事件侦听器嵌套在另一个方法中,则this将引用外部嵌套方法的上下文,并且我们无法再使用this访问添加事件侦听器的元素,就像我们在前面的代码示例中所做的那样。

幸运的是,这可以通过在元素上使用currentTarget方法轻松解决,如下所示:




输出:

[object HTMLButtonElement] Correctly identified!

正如我们所见,使用currentTarget允许我们访问添加事件侦听器的元素,同时this允许我们访问封闭函数的上下文——即: this允许我们成功调用 displayInfo() 方法。