• call、apply 以及 bind 的区别和用法


    call、apply、bind

    call和apply共同点

    • 共同点:改变函数执行时的上下文,将一个对象的方法交给另一个对象来执行,并且是立即执行的
    • call和apply的对象,必须是一个函数Function

    call和apply区别

    call的写法

    Function.call(obj, [param1[, param2[, ...[, paramN]]]])

    需要注意以下几点:

    • 调用call的对象,必须是个函数Function
    • call的第一个参数,是一个对象,Function的调用者,将会指向这个对象。如果不传,则默认为全局对象window
    • 第二个参数开始,可以接收任意个参数,每个参数会映射到相应位置的Function的参数上。
    • 但是如果将所有的参数作为数组传入,他们会作为一个整体映射到Function对应的第一个参数上,之后参数都为空
    function func(a,b,c) {}
    func.call(obj, 1,2,3) // func接收到的参数为1,2,3
    func.call(obj, [1,2,3]) // func接收到的参数为[1,2,3], undefined, undefined 
    
    • 1
    • 2
    • 3

    apply的写法

    Function.apply(obj[, argArray])

    需要注意的是:

    • 它的调用者必须是函数Function,并且只接受两个参数,第一个参数的规则与call一致
    • 第二个参数,必须是数组或者类数组,他们会被转换成类数组,传入到Function中,并且会被映射到Function对应的参数上,
    func.apply(obj, [1,2,3]) // func接收到的参数是1,2,3
    func.apply(obj, {0:1, 1:2, 2:3, length: 3}) // func接收到的参数是1,2,3 
    
    • 1
    • 2

    什么是类数组

    • 具备与数组特征类似的对象
    • 类数组无法使用forEach、splice、push等数组原型链上的方法

    call和apply的用途

    call的使用场景

    • 对象的继承
    function superClass() {this.a = 1this.print = function() {console.log(this.a)}
    }
    function subClass() {superClass.call(this)this.print()
    }
    subClass() // 1 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 借用方法* 类数组,如果想使用Array原型链上的方法* let demoNodes = Array.prototype.slice.call(document.getElementsByTagName("*"))

    apply 的用法

    • Math.max,用来获取数组中最大的一项* let max = Math.max.apply(null, array)
    • 实现两个数组合并
    let arr1 = [1, 2, 3]
    let arr2 = [4, 5, 6]
    Array.prototype.push.apply(arr1, arr2)
    console.log(arr1) // [1, 2, 3, 4, 5, 6] 
    
    • 1
    • 2
    • 3
    • 4

    bind的使用

    bind()方法创建一个新的函数,在调用时设置this关键字为提供的值,并在调用新函数时,将给定参数列表作为原函数的参数序列的前若干项

    Function.bind(thisArg, arg1, arg2])

    • bind方法与apply、call比较类似,也能改变函数体内的this指向,不同的是,bind方法的返回值是函数,并且需要稍后调用,才会执行。而apply和call则是立即调用
    • 如果bind的第一个参数是null或者undefined,this就指向全局对象window
    function add (a, b) {return a + b;
    }
    function sub (a, b) {return a - b;
    }
    add.bind(sub, 5, 3); // 这时,并不会返回 8
    add.bind(sub, 5, 3)(); // 调用后,返回 8 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    总结

    • call 和 apply 的主要作用,是改变对象的执行上下文,并且是立即执行的。它们在参数上的写法略有区别。* bind 也能改变对象的执行上下文,它与 call 和 apply 不同的是,返回值是一个函数,并且需要稍后再调用一下,才会执行。bind的模拟实现
      =========

    bind

    bind()方法创建一个新函数,当这个新函数被调用时,bind()的第一个参数将作为它运行时的this,之后的一序列参数将会在传递的实参钱传入作为它的参数

    function fn(a, b, c) {return a + b + c;
    }
    var _fn = fn.bind(null, 10);
    var ans = _fn(20, 30); // 60 
    
    • 1
    • 2
    • 3
    • 4

    它的特点:

    1.返回一个函数;
    2.可以传入参数

    实现bind最终代码

    Function.prototype.bind1 = function(context) {if (typeof this !== 'function') {throw new Error('Function.prototype.bind --what is trying to be bound is not callable')}var self = thisvar args = Array.prototype.slice.call(arguments, 1)var fNOP = function () {}var fBound = function() {var bindArgs = Array.prototype.slice.call(arguments) // 当作为构造函数时,this 指向实例,此时结果为 true,将绑定函数的 this 指向该实例,可以让实例获得来自绑定函数的值// 以上面的是 demo 为例,如果改成 `this instanceof fBound ? null : context`,实例只是一个空对象,将 null 改成 this ,实例会具有 habit 属性// 当作为普通函数时,this 指向 window,此时结果为 false,将绑定函数的 this 指向 contextreturn self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs))}fNOP.prototype = this.prototypefBound.prototype = new fNOP()return fBound
    } 
    
    • 1
    • 2
  • 相关阅读:
    netdata数据持久化配置
    四、一般页面制作《仿淘票票系统前后端完全制作(除支付外)》
    神经网络硕士就业前景,神经网络就业怎么样
    编译后的go程序无法在alpine基础镜像创建的容器运行问题
    C语言基础知识入门
    大模型携手AI原生应用融入产业场景
    抽象工厂模式-C++实现
    「学习笔记」FHQ-treap
    【Vue实战】基于Vue的九宫格在线抽奖附源代码
    MathType2024最新word公式编辑器
  • 原文地址:https://blog.csdn.net/web2022050903/article/details/126054681