千家信息网

怎么实现call、apply、bind

发表于:2025-01-24 作者:千家信息网编辑
千家信息网最后更新 2025年01月24日,本篇内容介绍了"怎么实现call、apply、bind"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
千家信息网最后更新 2025年01月24日怎么实现call、apply、bind

本篇内容介绍了"怎么实现call、apply、bind"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

首先我们来给call下个定义:

call方法在使用一个指定的 this 值和若干个指定的参数值的前提下调用某个函数或方法。

举个例子:

var foo = {    value: 1};
function bar() { console.log(this.value);}
bar.call(foo); // 1

从上面代码的执行结果,我们可以看到,call首先改变了this的指向,使函数的this指向了foo,然后使bar函数执行了。

总结如下:1、call改变函数this指向,2、调用函数

思考一下:我们如何实现上面的效果呢?代码改造如下:

//将bar函数挂载到foo对象上,使其成为foo的方法,用foo.bar来调用var foo = {    value:1,    bar:function(){        console.log(this.value)    }}foo.bar()     //1

仔细观察一下我们做了什么,将bar函数挂载到foo对象上,使其成为foo的方法,用foo.bar来调用。

再来看上面代码的执行结果:打印1,有没有什么启发呢?为了模拟call方法,我们可不可以这样做呢:

a、将函数设为某个对象的属性(或者方法)

b、通过该对象的属性调用该函数

c、将该对象上的这个属性(或者方法)

代码如下:

Function.prototype.myCall = function(context) {  context = context || window  //将函数挂载到对象的fn属性上  context.fn = this  //处理传入的参数  const args = [...arguments].slice(1)  //通过对象的属性调用该方法  const result = context.fn(...args)  //删除该属性  delete context.fn  return result}

我们看一下上面的代码:

1、首先我们对参数context做了兼容处理,不传值,context默认值为window。

2、然后我们将函数挂载到context上面,context.fn = this;

3、处理参数,将传入myCall的参数截取,去除第一位,然后转为数组;

4、调用context.fn,此时fn的this指向context;

5、删除对象上的属性 delete context.fn

5、将结果返回。

以此类推,我们顺便实现一下apply,唯一不同的是参数的处理,代码如下:

Function.prototype.myApply = function(context) {
context = context || window context.fn = this let result // myApply的参数形式为(obj,[arg1,arg2,arg3]); // 所以myApply的第二个参数为[arg1,arg2,arg3] // 这里我们用扩展运算符来处理一下参数的传入方式 if (arguments[1]) { result = context.fn(...arguments[1]) } else { result = context.fn() } delete context.fn return result}

以上便是call和apply的模拟实现,唯一不同的是对参数的处理方式。

接着再来思考一下bind的实现,在模拟bind的实现之前,先看一下bind的使用案例:

var obj = {a:1};function bar(){    console.log(this.a);}bar.bind(obj)();

我们看到,bind函数虽然也能改变bar函数的this,但是改变后,函数并不会执行,只是返回一个新的函数,想执行就得继续调用,仔细观察第五行代码的写法。

根据上面的使用案例,我们先实现一个简单版本的bind:

Function.prototype.myBind = function(ctx) {    return () => { // 要用箭头函数,否则 this 指向错误        return this.call(ctx)    }}var obj = {a:1};function bar(){    console.log(this.a);}bar.myBind(obj)();

但是这样比较简陋,函数的参数一多就不能处理了,如下面这种情况:

bar.bind(obj, 2)(2)// orbar.bind(obj)(2, 2)

为了兼容bind调用时满足参数传递的不同方式,代码修改如下:

Function.prototype.myBind = function(ctx, ...argv1) {    return (...argv2) => {        return this.call(ctx, ...argv1, ...argv2)    }}//测试代码var obj = {a:1};function bar(b,c){    console.log(this.a+b+c);}bar.myBind(obj)(20,30);bar.myBind(obj,20,30)();

"怎么实现call、apply、bind"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

函数 参数 代码 对象 方法 属性 处理 指向 不同 方式 案例 结果 面的 其成 内容 情况 更多 知识 观察 实用 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 联想服务器在哪买 金山区智能软件开发培训 网络安全你我共守护手抄报 如何学习电脑网络安全知识 家长对网络安全心得体会 软件开发打开代码 康泰医学软件开发工程师 数据库SQL表格 数据库结构如何给别人讲解 请简述客户机服务器的工作模式 网络安全基础txt 腾讯云的服务器地址 e3做服务器 当数据库的恢复模式为 建筑技术开发维普数据库收录吗 网络安全面临的风险有哪些方面 服务器boot安全启动 学大数据以后可以从事软件开发吗 软件开发步骤包括哪些过程 榆次软件开发 常用的中外文文献数据库 东城区综合软件开发大概费用 以聚焦网络安全为标题的作文 无法从u盘读取数据库 怎么关闭服务器管理器自启 安居客研究院数据库 门户网站网络安全管理办法 程序员学习数据库 车载无线网络技术分析及应用 中越水果贸易联合国商品贸易统计数据库
0