最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 一次搞懂bind、apply和call

    正文概述 掘金(大威Wayne)   2021-08-09   528

    最近在面试一些公司,发现考察 JS 基础的公司非常多,有一次问到了 bindapplycall 的区别,当场没答上来。这次就好好来复习一下 bindapplycall 的用法。

    这三个方法的共同点在于改变 this 指向,能够把一个对象的方法交给另一个对象来执行,并且 applycall 是立即执行的。

    为什么要改变 this 指向呢?比如A对象有一个 say 方法,B对象需要用到这个方法,我们不需要专门为B重新写这个方法,只需要借用A的方法即可。

    apply

    MDN文档上对其的解释为:

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

    fn.apply(obj, [argsArray])
    

    需要注意的是,apply 的调用者必须是函数,第二个参数必须是数组或者类数组,他们会被转换成数组传入 fn,映射到 fn 对应的参数上。这是 apply 和 call 之间很重要的区别。

    我们可以使用 apply 来计算一个数组中的最大值:

    const numbers = [5, 6, 2, 3, 7]
    
    const max = Math.max.apply(null, numbers);
    
    console.log(max);
    // 输出结果: 7
    

    还可以将一个数组中的每一项添加到另一个数组:

    let array = ['a', 'b'];
    let elements = [0, 1, 2];
    array.push.apply(array, elements);
    console.info(array); 
    // ["a", "b", 0, 1, 2]
    

    上文有提到类数组,那什么是类数组呢?

    一般数组的特征有:

    • 可以通过 index 来进行查询,比如 array[0]
    • 数组长度属性 length
    • 可通过 for 循环和 forEach 方法遍历。

    类数组就是和数组有类似特征的对象(你没看错,类数组是个对象),比如下面这个对象:

    let array = {
        0: 1,
        1: 2,
        2: 3,
        length: 3
    };
    

    这个 array 对象可以通过 index 调用,具有 length 属性,同时也可以通过 for循环来遍历。

    注意:类数组无法使用 forEach、splice、push 等数组原型链上的方法,毕竟类数组不是真数组。


    call

    call和apply比较类似,区别在于call方法接受的是参数列表,而apply接受的是一个参数数组。MDN 对 call 的解释为:

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

    fn.call(obj, a, b, ...)
    

    关于 call 需要注意:

    • 调用 call 的对象和 apply 一样,必须是个函数;
    • call 的第一个参数是一个对象,如果不传,默认为全局对象 window
    • 第二个参数开始,可以接受任意个参数,每个参数都会映射到相应位置的 fn 的参数上;
    • 如果将所有参数作为数组传入,他们会作为一个整体映射到 fn 对应的第一个参数上,之后的参数都为空。
    fn.call(obj, 1, 2, 3)
    // fn 接收的参数为 1, 2, 3
    
    fn.call(obj, [1,2,3])
    // fn 接收的参数实际上是 [1,2,3], undefined, undefined
    

    bind

    MDN 对 bind 的解释为:

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

    bind 的语法如下:

    fn.bind(obj[, arg1[, arg2[, ...]]])
    

    bind 一样能改变函数的 this 指向,不过 bind 的返回值是函数,并且需要稍后调用才能执行。如果 bind 的第一个参数是 null 或者 undefinedthis 就指向全局对象 window

    const module = {
    	x: 12,
      getX: function(){
      	return this.x;
      }
    }
    
    const unboundGetX = module.getX;
    // unboundGetX 为 undefined
    
    const boundGetX = unboundGetX.bind(module)
    // boundGetX 为 42
    

    来一个总结

    • apply、call和bind都能改变对象执行上下文;
    • apply接收参数为数组或类数组,call 接收的是参数列表,bind接收的是函数;
    • apply和call是立即执行,bind需要稍后调用才会执行。

    起源地下载网 » 一次搞懂bind、apply和call

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元