JavaScript中的call,apply,bind方法详解及简单实现 您所在的位置:网站首页 in-call JavaScript中的call,apply,bind方法详解及简单实现

JavaScript中的call,apply,bind方法详解及简单实现

2024-02-25 04:45| 来源: 网络整理| 查看: 265

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

call, apply, 和 bind 是 JavaScript 中常用的函数。它们的作用是在函数调用时动态地改变函数的上下文。具体来说,它们可以指定函数中的 this 指向哪个对象,以及传递参数给函数。

call

call 函数允许你在一个特定的上下文中调用一个函数。它的语法如下:

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

其中,context 是指定函数中的 this 关键字指向的对象,arg1, arg2, ... 是传递给函数的参数。

下面是一个例子,其中 obj 对象中有一个 greeting 方法:

const obj = { name: 'Alice', greeting: function() { console.log(`Hello, my name is ${this.name}`); } }; obj.greeting(); // 输出 "Hello, my name is Alice"

现在,假设我们要将 greeting 方法应用于另一个对象 person,并让 this 关键字指向 person 对象。我们可以使用 call 函数来实现:

const person = { name: 'Bob' }; obj.greeting.call(person); // 输出 "Hello, my name is Bob"

这里,我们使用 call 函数将 obj 对象的 greeting 方法应用于 person 对象。由于我们使用了 call 函数,并将 person 对象作为参数传递给它,因此 greeting 方法中的 this 关键字会指向 person 对象,而不是 obj 对象。

apply

apply 函数与 call 函数类似,它也允许你在一个特定的上下文中调用一个函数。不同之处在于,apply 函数需要将参数作为数组传递。它的语法如下:

function.apply(context, [argsArray])

其中,context 是指定函数中的 this 关键字指向的对象,argsArray 是一个数组,其中包含要传递给函数的参数。

下面是一个例子,其中 obj 对象中有一个 greeting 方法:

const obj = { name: 'Alice', greeting: function(city, country) { console.log(`Hello, my name is ${this.name} and I am from ${city}, ${country}`); } }; obj.greeting('New York', 'USA'); // 输出 "Hello, my name is Alice and I am from New York, USA"

现在,假设我们要将 greeting 方法应用于另一个对象 person,并让 this 关键字指向 person 对象,并且传递一个数组作为参数。我们可以使用 apply 函数来实现:

const person = { name: 'Bob' }; obj.greeting.apply(person, ['London', 'UK']); // 输出 "Hello, my name is Bob and I am from London, UK"

这里,我们使用 apply 函数将 obj 对象的 greeting 方法应用于 person 对象,并将数组 ['London', 'UK'] 作为参数传递给它。由于我们使用了 apply 函数,并将 person 对象和数组作为参数传递给它,因此 greeting 方法中的 this 关键字会指向 person 对象,而参数 'London' 和 'UK' 也会被传递给 greeting 方法。

bind

bind 函数与 call 和 apply 函数不同,它不会立即调用函数。相反,它返回一个新函数,该函数将绑定到指定的上下文,当该函数被调用时,它将以指定的上下文运行。它的语法如下:

function.bind(thisArg, arg1, arg2, ...)

其中,thisArg 是指定函数中的 this 关键字指向的对象,arg1, arg2, ... 是传递给函数的参数。与 call 和 apply 不同,bind 函数不会立即调用函数,而是返回一个新的函数,你可以将它存储在变量中,然后在需要时调用。

下面是一个例子,其中 obj 对象中有一个 greeting 方法:

const obj = { name: 'Alice', greeting: function(city, country) { console.log(`Hello, my name is ${this.name} and I am from ${city}, ${country}`); } }; const person = { name: 'Bob' }; const boundGreeting = obj.greeting.bind(person, 'London'); boundGreeting('UK'); // 输出 "Hello, my name is Bob and I am from London, UK"

这里,我们使用 bind 函数将 obj 对象的 greeting 方法绑定到 person 对象上,并且传递 'London' 参数。bind 函数返回一个新的函数 boundGreeting,我们将其存储在变量中。当我们调用 boundGreeting('UK') 时,它会以 person 对象为上下文,以 'London' 和 'UK' 作为参数调用 greeting 方法。

简单实现

以下是一个简单的实现,展示了如何使用 JavaScript 实现 call、apply 和 bind 函数:

// 实现 call 方法 Function.prototype.myCall = function (context, ...args) { // 如果 context 参数为空,则默认为 window 对象 context = context || window; // 使用 Symbol 函数创建一个唯一的标识符 const fnSymbol = Symbol(); // 将原始函数存储为 context 对象的属性 context[fnSymbol] = this; // 调用函数并将结果存储在 result 变量中 const result = context[fnSymbol](...args); // 删除 context 对象的属性 delete context[fnSymbol]; // 返回函数的结果 return result; }; // 实现 apply 方法 Function.prototype.myApply = function (context, args) { // 如果 context 参数为空,则默认为 window 对象 context = context || window; // 使用 Symbol 函数创建一个唯一的标识符 const fnSymbol = Symbol(); // 将原始函数存储为 context 对象的属性 context[fnSymbol] = this; // 调用函数并将结果存储在 result 变量中 const result = context[fnSymbol](...args); // 删除 context 对象的属性 delete context[fnSymbol]; // 返回函数的结果 return result; }; // 实现 bind 方法 Function.prototype.myBind = function (context, ...args) { // 将 this 存储在 fn 变量中 const fn = this; // 返回一个新的函数,该函数将传入的参数与新函数的参数合并,并在新的上下文中使用 apply 调用原始函数 return function (...newArgs) { return fn.apply(context, [...args, ...newArgs]); }; };

这里,我们使用原型方法给 Function 对象添加了 myCall、myApply 和 myBind 方法。 myCall 和 myApply 非常相似,它们的不同之处在于参数传递方式。 myCall 函数使用剩余参数语法 ...args 来传递参数,而 myApply 函数接受一个数组作为参数。 myBind 函数返回一个新的函数,该函数接受一个参数,并将其与 myBind 中传递的参数合并,然后调用原始函数。

对于 myCall 和 myApply,我们首先将传入的 context 参数与 window 对象进行比较,如果 context 是空的,则默认为全局 window 对象。然后,我们使用 Symbol 函数创建一个唯一的标识符 fnSymbol,并将原始函数存储为 context[fnSymbol] 的属性。我们然后调用函数,将结果存储在 result 变量中,并使用 delete 关键字从 context 对象中删除函数属性。最后,我们返回函数的结果。

对于 myBind,我们首先将 this 存储在 fn 变量中,然后返回一个新的函数,该函数使用剩余参数语法将 myBind 中传递的参数与新函数的参数合并,并在新的上下文中使用 apply 调用原始函数。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有