首页 > 其他分享 >call(),bind(),apply(),的区别和手写

call(),bind(),apply(),的区别和手写

时间:2024-11-10 16:18:03浏览次数:3  
标签:const 函数 bind console call thisArg apply log

1.call(),bind(),apply()的区别

call(), bind(), 和 apply() 是 JavaScript 中用于改变函数执行上下文(即 this 的指向)的方法,它们之间有一些区别:

  1. call():
    • call() 方法允许你调用一个具有指定 this 值的函数,并且允许你传递一个参数列表。
    • 它的语法是 function.call(thisArg, arg1, arg2, ...), 其中 thisArg 是函数执行时 this 的值,后面的参数 arg1, arg2, … 是传递给函数的参数列表。
    • call() 方法会立即执行函数,并且可以立即传递参数列表。
  2. apply():
    • apply() 方法与 call() 类似,但它接受一个参数数组作为函数的参数列表。
    • 它的语法是 function.apply(thisArg, [argsArray]), 其中 thisArg 是函数执行时 this 的值,argsArray 是一个数组,包含传递给函数的参数列表。
    • apply() 方法也会立即执行函数,并且传递的参数是一个数组。
  3. bind():
    • bind() 方法用于创建一个新函数,并且在调用时将一个指定的 this 值绑定到函数中,不会立即执行函数。
    • 它的语法是 function.bind(thisArg, arg1, arg2, ...), 其中 thisArg 是函数执行时 this 的值,后面的参数 arg1, arg2, … 是绑定到新函数的参数列表。
    • bind() 方法返回一个新函数,当调用这个新函数时,会以指定的 this 值和参数列表执行原函数。
      下面是对这三个方法的详细说明:
  • call() 示例:
const person = {
  fullName: function(city, country) {
    return this.firstName + " " + this.lastName + ", " + city + ", " + country;
  }
};
const person1 = {
  firstName: "John",
  lastName: "Doe"
};
const person2 = {
  firstName: "Mary",
  lastName: "Doe"
};
// 使用 call() 方法调用 person 对象的 fullName 方法,并传递参数
console.log(person.fullName.call(person1, "Oslo", "Norway")); // 输出: John Doe, Oslo, Norway
console.log(person.fullName.call(person2, "Stockholm", "Sweden")); // 输出: Mary Doe, Stockholm, Sweden
  • apply() 示例:
const numbers = [5, 6, 2, 3, 7];
// 使用 apply() 方法调用 Math.max 函数,传递一个数组作为参数
const max = Math.max.apply(null, numbers);
console.log(max); // 输出: 7
  • bind() 示例:
const module = {
  x: 42,
  getX: function() {
    return this.x;
  }
};
const unboundGetX = module.getX;
const boundGetX = unboundGetX.bind(module);
console.log(unboundGetX()); // 输出: undefined,因为 this 指向全局对象
console.log(boundGetX()); // 输出: 42,因为使用 bind() 绑定了 module 对象

总的来说,call()apply() 方法用于立即调用函数并且改变函数执行上下文,而 bind() 方法用于创建一个新函数,不会立即执行,并且可以绑定指定的 this 值。

2.代码

/* 
    手写apply方法
    1.定义call方法
    2.设置this(改变this指向)和调用原函数
    3.接收剩余参数和返回结果
     */
//1.定义myCall方法(这个方法应在原型对象上,因为其他函数是Function的实例)
Function.prototype.myApply = function (thisArg,args) {//args为数组
        //2.设置this(改变this指向)和调用原函数
        //设置this
        const key = Symbol('key')
        thisArg[key] = this   //可以理解为给这个对象加了一个方法
        //3.接收剩余参数和返回结果
        console.log(args);//arg是一个数组
        const res = thisArg[key](...args)//调用这个方法
        delete thisArg[key]//把this刚添加的东西删除,就得到了原来的内容
        return res
    }
    //测试代码
    const food = {
        name: '薯片'
    }
    function func(num1, num2) {
        console.log(this);
        return num1 + num2
    }
    //调用mycall方法
    const res = func.myApply(food, [2, 3])
    console.log(res);
 /* 
    手写call方法
    1.定义call方法
    2.设置this(改变this指向)和调用原函数
    3.接收剩余参数和返回结果
    4.使用Symbol调优,解决this所指内容的属性名重复问题
     */
    //1.定义myCall方法(这个方法应在原型对象上,因为其他函数是Function的实例)
    Function.prototype.myCall = function (thisArg, ...args) {
        //2.设置this(改变this指向)和调用原函数
        //设置this
        const key = Symbol('key')
        thisArg[key] = this   //可以理解为给这个对象加了一个方法
        //3.接收剩余参数和返回结果
        console.log(args);//arg是一个数组
        const res = thisArg[key](...args)//调用这个方法
        delete thisArg[key]//把this刚添加的东西删除,就得到了原来的内容
        return res
    }

    //测试代码
    const food = {
        name: '薯片'
    }
    function func(num1, num2) {
        console.log(this);
        return num1 + num2
    }
    //调用mycall方法
    const res = func.myCall(food, 2, 3)
    console.log(res);

 /* 
        手写bind方法
        1.定义myBind方法
        2.返回绑定this的新函数
        3.合并绑定和新传入的参数
         */
        // 1.定义myBind方法
        Function.prototype.myBind = function (thisArg, ...args) {
            //2.返回绑定this的新函数
            return (...funArgs) => {
                //3.合并绑定和新传入的参数
             return this.call(thisArg,...args,...funArgs)
            }
        }
        //测试代码
        const food = {
            name: '薯片'
        }
        function func(num1, num2) {
            console.log(this);
            return num1 + num2
        }
        //调用myBind方法
        const newFunc = func.myBind(food, 4)
        const res=newFunc(2)
        console.log(res);

标签:const,函数,bind,console,call,thisArg,apply,log
From: https://blog.csdn.net/z142536x/article/details/143497102

相关文章

  • ffmpeg RFC call
    IntheRFCmode,onepersonfromtheTCpostsonthemailinglistthetechnicalquestionandwillrequestinputfromthecommunity.Themailwillhavethefollowingspecification:aprecisetitleaspecifictag[TCRFC]atop-levelemailcontainaprecise......
  • bind:chooseavatar不兼容问题
    constv1=wx.getSystemInfoSync().SDKVersion;letversion="";if(!!v1){version=v1;}else{version=wx.getAppBaseInfo().SDKVersion;}if(this.compareVersion(version,'2.21.2')>=0){this.set......
  • 解决微信小程序地图callout气泡在ios展示,在安卓机不展示
    前段时间和小伙伴们接了一个租房小程序的单子,其中有个地图找房功能,项目已经交付了一一段时间,由于我们和客户都没有安卓机,于是在地图有个bug我们都没发现。    bug复现:我们使用了小程序的marker标记点用于标记展示,由于有个自带的小图标,我们用不上自带的小图标,于是直接a......
  • Springboot 配置yml文件 ENC 加密及failed to bind properties under '********' to j
    1.添加依赖<dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><version>3.0.3</version></dependency>2.设置加密盐......
  • 0基础学Python——面向对象-可迭代、面向对象-迭代器、call方法、call方法实现装饰器
    0基础学Python——面向对象-可迭代、面向对象-迭代器、call方法、call方法实现装饰器、计算函数运行时间面向对象--可迭代实现方法面向对象--迭代器实现方法call方法作用call方法实现装饰器代码演示计算函数运行时间代码演示面向对象–可迭代把对象看做容器,存储......
  • HAL_UART_RxCpltCallback与HAL_UARTEx_RxEventCallback使用场景
    1.HAL_UART_RxCpltCallback()是在接收到启动时设置的字节数(启动接收时需要设置接收数据长度)后的回调。适用于标准的接收模式,比如使用HAL_UART_Receive_IT或HAL_UART_Receive_DMA启动的接收。在处理完接收数据后,还需要重新启动接收(要在回调函数中调用HAL_UART_Receive_IT或HAL_......
  • python openai 通过Function Call 创建自动化任务
    目录一、什么是FunctionCall(函数掉用)1. 功能概述2. 工作原理二、如何实现函数调用1、定义自己的get_weather函数2、给助手添加函数调用3、写好instrction,指导assistant去掉用你定义的方法。4、最后也是最重要的,捕获Assistant的FunctionCall三、常见问题四、......
  • c语言:动态内存管理中的malloc和free,calloc和realloc
    为什么要有动态内存分配?通过之前的学习,我们已经掌握的内存开辟方式有:inta=20;//在栈空间上开辟四个字节chararr[10]={0};//在栈空间上开辟10个字节的连续空间上述空间的开辟的大小是固定的数组在申明的时候,必须指定数组的长度,数组空间一旦确定了大小不能进行调整。......
  • 线程池ThreadPoolExecutor配合callable获得线程执行结果
    此处记录使用callable创建线程,使用线程池执行,看下是否有进行线程复用并且FutureTask返回结果线程创建publicclassMyCallableBakeUserimplementsCallable<String>{privateinta;publicMyCallableBakeUser(inta){this.a=a;}@Overrid......
  • 新手逆向实战三部曲之三——通过进入关键call追码注册软件(进阶)
    教程开始:通过前两次的学习,是不是感觉逆向也蛮有意思的呢,感兴趣的同学可以先看看前二次的内容再继续向下学习新手逆向实战三部曲之一新手逆向实战三部曲之二有了上次爆破的基础,这次便省力了许多,这次从载入开始,虽前头的几个步骤与之前相同,温故而知新嘛(也可直接往后看)用OD......