JavaScript 解释call()、apply()和bind()方法
在实现bind()、apply()和call()的polyfill之前,让我们先了解一下在JavaScript中polyfill的含义:
Polyfill: Polyfill是对我们的浏览器提供的功能进行实现的方法,但在其以前的版本中可能还不存在。
1. Bind()方法 : bind()方法创建一个新的函数,并在调用该新函数时将 this 关键字设置为传递给bind方法的第一个参数。如果在bind方法之前传递了其他序列的参数作为新函数的参数进行调用。
语法:
示例1: 首先,让我们看一下javascript提供的bind方法的实际输出:
JavaScript
输出:
在这里我们有一个名为“PrintName”的对象,它有一个叫做sayHi的函数,它将打印我们在名为nameObj的对象中传递的人的名字。在这里,我们将nameObj与PrintName的sayHi函数绑定在一起,这样我们就可以在PrintName的sayHi函数中访问nameObj。 this 在PrintName的sayHi函数中,bind方法返回一个函数,这样当我们调用这个函数时,sayHi将有 this 作为nameObj。
例如2: 现在让我们编写我们自己的bind polyfill。我们将使用上面示例中Object类的原型来实现我们的bind polyfill:
JavaScript
输出:
解释: 因此,我们的 bind polyfill 给出了与之前的 bind 方法相同的输出。现在让我们看看我们实际上在做什么。在 Object 原型中,我们附加了我们的 MyBind 函数。我们的 MyBind 函数以一个对象(在我们的例子中是 nameObj)作为参数,我们希望将其与我们的 PrintName sayHi 函数绑定在一起。
现在,让我们只专注于代码的这一部分(Object.prototype.MyBind):
在这里,我们有一个名为MyBind的函数,其中一个参数是bindObj,在我们的例子中,bindObj是nameObj。那么实际上我们在做什么呢?我们在nameObj中添加了myMethod,并且在myMethod中存储了 this 。在我们的例子中, this 就是sayHi函数。
例子3: 让我们先看看在运行“bindObj.myMethod=this”这行代码之后,我们的bindObj是什么样子。
Javascript
输出:
在这里,我没有调用HiFun(),因为我们只想看看在运行“bindObj.myMethod=this”之后bindObj的样子。我们可以清楚地看到在bindObj中有一个名为myMethod的函数,它具有sayHi函数。我们还可以看到在运行“bindObj.myMethod=this”行后,bindObj的图示表示。如果我们不能理解上面的输出结果,可以查看下面的代码:
所以,我们为什么要做这些呢?我们想要在PrintName的sayHi函数中访问nameObj。我们想要编写一个bind的polyfill。所以我们不是将nameObj附加到sayHi函数中的this上。我们所做的是在nameObj本身中创建一个myMethod,在myMethod中添加PrintName的sayHi函数,然后在MyBind中返回一个函数,其中调用了bindObj.MyMethod(),这实际上意味着调用nameObj.myMethod(),因此当在nameObj内部调用sayHi函数时,它将包含在自身的this中,并且会打印出nameObj中的name,即Tony。
示例4: 让我们看一个更多的bind polyfill的例子,当参数被传递给我们的MyBind方法时:
JavaScript
输出:
在这里,“…args”是将n个输入放入javascript数组中的剩余参数。 在这里,“…args”将是[42]。
call() 方法: call() 方法直接调用函数,并将 this 设置为传递给call方法的第一个参数。如果在call方法之前传递了其他序列的参数,则它们将作为函数的参数传递。
语法:
示例1: 在实现自己的调用填充之前,让我们先看一下javascript提供的调用方法
Javascript
输出:
注意: call方法不返回新的函数。
示例2: 现在让我们自己编写call的填充方法:
Javascript
输出:
这与MyBind函数完全相同,但唯一的区别是它不返回一个函数,因为由javascript提供的调用方法也不返回一个方法。因此,在实现call的polyfill时,我们还需要记住这一点。
Apply()方法: apply()方法直接调用函数,并将 this 设置为传递给apply方法的第一个参数,如果其他参数以数组形式传递给call方法,则它们作为参数传递给函数。
语法:
示例1: 最后一次让我们看一下Javascript提供的apply方法:
Javascript
输出:
在apply方法中,我们以数组形式传递参数,这是call和apply之间的主要区别。
示例2: 现在让我们编写我们的最终polyfill,即apply polyfill:
JavaScript
输出:
现在在这个应用填充中,我们只需要将一个数组作为参数传递。其余部分与调用填充是相同的。