文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

如何使用JS简单实现apply、call和bind方法

2023-06-29 05:40

关注

这篇文章主要讲解了“如何使用JS简单实现apply、call和bind方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何使用JS简单实现apply、call和bind方法”吧!

1.方法介绍

apply、call和bind都是系统提供给我们的内置方法,每个函数都可以使用这三种方法,是因为apply、call和bind都实现在了Function的原型上(Function.prototype),而他们的作用都是给我们函数调用时显式绑定上this。下面先介绍一下它们的基本用法:

apply方法:调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。

使用语法:func.apply(thisArg, [argsArray])

thisArg:在func函数调用时绑定的this值;[argsArray]:一个数组或者类数组对象,其中的数组元素将作为单独的参数传给func函数;

使用效果:

function foo(x, y ,z) {  console.log(this, x, y, z)}const obj = { name: 'curry', age: 30 }foo.apply(obj, [1, 2, 3])

如何使用JS简单实现apply、call和bind方法

call方法:使用一个指定的 this值和单独给出的一个或多个参数来调用一个函数。

使用语法:func.call(thisArg, arg1, arg2, ...)

thisArg:在func函数调用时绑定的this值;arg1, arg2, ...:指定的参数列表,将作为参数传递给func函数;

使用效果:

function foo(x, y ,z) {  console.log(this, x, y, z)}const obj = { name: 'curry', age: 30 }foo.call(obj, 'a', 'b', 'c')

如何使用JS简单实现apply、call和bind方法

bind方法:创建一个新的函数,在bind()被调用时,这个新函数的this被指定为bind()的第一个参数,而其余参数将作为新函数的参数,供调用时使用。

使用语法:func.bind(thisArg[, arg1[, arg2[, ...]]])

thisArg:调用func函数时作为this参数传递给目标函数的值;arg1, arg2, ...:当目标函数被调用时,被预置入func函数的参数列表中的参数;

使用效果:

function foo(...args) {  console.log(this, ...args)}const obj = { name: 'curry', age: 30 }const newFoo = foo.bind(obj, 1, 2, 3)newFoo()newFoo('a', 'b', 'c')

如何使用JS简单实现apply、call和bind方法

总结:

apply和call主要用于在函数调用时给函数的this绑定对应的值,两者作用类似,主要区别就是除了第一个参数,apply方法接受的是一个参数数组,而call方法接受的是参数列表。

bind也是给函数指定this所绑定的值,不同于apply和call的是,它会返回一个新的函数,新函数中的this指向就是我们所指定的值,且分别传入的参数会进行合并。

2.apply、call和bind方法的实现

为了所有定义的函数能够使用我们自定义的apply、call和bind方法,所以需要将自己实现的方法挂在Function的原型上,这样所有的函数就可以通过原型链找到自定义的这三个方法了。

2.1.apply的实现

Function.prototype.myApply = function(thisArg, argArray) {  // 1.获取当前需要被执行的函数  // 因为myApply是需要被当前函数进行调用的,根据this的隐式绑定,此处的this就是指向当前需要被执行的函数  const fn = this  // 2.对传入的thisArg进行边界判断  if (thisArg === null || thisArg === undefined) {    // 当传入的是null或者undefined是,被执行函数的this直接指向全局window    thisArg = window  } else {    // 将传入的thisArg对象化,方便后面在thisArg添加属性    thisArg = Object(thisArg)  }  // 也可简单写成三元运算符:  // thisArg = (thisArg === null || thisArg === undefined) ? window : Object(thisArg)  // 3.将获取的fn添加到thisArg对象上  // 这里使用Symbol的原因是避免外部传入的thisArg中的属性与添加fn有冲突  const fnSymbol = Symbol()  Object.defineProperty(thisArg, fnSymbol, {    enumerable: false,    configurable: true,    writable: false,    value: fn  })  // 也可简单写成  // thisArg[fnSymbol] = fn  // 4.对argArray进行判断  // 看是否有传入值,没有值传入就默认 []  argArray = argArray || []  // 5.调用获取的fn函数,并将对应传入的数组展开传递过去  const result = thisArg[fnSymbol](...argArray)  // 调用完后删除添加的属性  delete thisArg[fnSymbol]  // 6.将结果返回  return result}

测试:虽然打印出来的对象中还存在Symbol属性,实际上已经通过delete删除了,这里是对象引用的问题。

function foo(x, y, z) {  console.log(this, x, y, z)}foo.myApply({name: 'curry'}, [1, 2, 3])

如何使用JS简单实现apply、call和bind方法

2.2.call的实现

call方法的实现和apply方法的实现差不多,主要在于后面参数的处理。

Function.prototype.myCall = function(thisArg, ...args) {  // 1.获取当前需要被执行的函数  const fn = this  // 2.对传入的thisArg进行边界判断  thisArg = (thisArg === null || thisArg === undefined) ? window : Object(thisArg)  // 3.将获取的fn添加到thisArg对象上  const fnSymbol = Symbol()  thisArg[fnSymbol] = fn  // 4.调用获取的fn函数,并将对应传入的args传递过去  const result = thisArg[fnSymbol](...args)  // 调用完后删除添加的属性  delete thisArg[fnSymbol]  // 5.将结果返回  return result}

测试:

function foo(x, y, z) {  console.log(this, x, y, z)}foo.myCall({name: 'curry'}, 1, 2, 3)

如何使用JS简单实现apply、call和bind方法

2.3.bind的实现

bind方法的实现稍微复杂一点,需要考虑到参数合并的问题。

Function.prototype.myBind = function(thisArg, ...argsArray) {  // 1.获取当前的目标函数,也就是当前使用myBind方法的函数  const fn = this  // 2.对传入的thisArg进行边界判断  thisArg = (thisArg === null || thisArg === undefined) ? window : Object(thisArg)  // 3.将获取的fn添加到thisArg对象上  const fnSymbol = Symbol()  thisArg[fnSymbol] = fn  // 4.定义一个新的函数  function newFn(...args) {    // 4.1.合并myBind和newFn传入的参数    const allArgs = [...argsArray, ...args]    // 4.2.调用真正需要被调用的函数,并将合并后的参数传递过去    const result = thisArg[fnSymbol](...allArgs)    // 4.3.调用完后删除添加的属性    delete thisArg[fnSymbol]    // 4.4.将结果返回    return result  }  // 6.将新函数返回  return newFn}

测试:

function foo(x, y, z) {  console.log(this, x, y, z)}const newFoo = foo.myBind({ name: 'curry' }, 1, 2)newFoo(3)

如何使用JS简单实现apply、call和bind方法

感谢各位的阅读,以上就是“如何使用JS简单实现apply、call和bind方法”的内容了,经过本文的学习后,相信大家对如何使用JS简单实现apply、call和bind方法这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯