最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 前端面试系列-JavaScript-call、applay、bind的区别及代码实现

    正文概述 掘金(random__)   2021-03-25   292

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

    一、call

    call 的写法

    Function.call(obj,[param1[,param2[,…[,paramN]]]])
    
    var name = 'name'
    var obj = {
     name: 'objName'
    }
    function getName(p1, p2) {
     console.log(p1, p2,this.name)
    }
    getName(1, 2) //1 2 "name"
    getName.call(obj, 1, 2)//1 2 "objName"
    

    需要注意以下几点:

    • 调用 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
    

    call模拟实现

    1. 明确是谁调用call:函数。
    2. call接收的第一个参数是要改变的this指向(去执行这个函数)。若无指定,默认为window
    3. call接收的后续参数就是作为调用call的那个函数所需的参数。
    function myCall(context) {
      //判断一下
      if (typeof this !== 'function'){
    	throw new TypeError('error')
      }
      //this指向,谁去执行去这个函数
      context = context || window
      //要执行的函数
      context.fn = this
      //取出参数
      const args = [...arguments].slice(1)
      //执行函数
      const result = context.fn(...args)
      //删除fn
      delete context.fn
      return result
    }
    

    验证一下

    Function.prototype.myCall = myCall
    getName.myCall(obj, 1, 2)//1 2 "objName"
    

    二、applay

    apply使用与call大体一致,只是接受参数的方法不同。call可以接收多个参数。apply接收的第一个参数是this,第二个参数是 所需参数所组成的数组。

    Function.apply(obj[,argArray])
    

    applay模拟实现

    function myApply(context) {
      if (typeof this !== 'function') {
        throw new TypeError('Error');
      }
      context = context || window;
      context.fn = this;
      var result;
      if (arguments[1]) {
        result = context.fn(...arguments[1]);
      } else {
        result = context.fn();
      }
      delete context.fn;
      return result;
    }
    

    三、bind

    Function.bind(thisArg[, arg1[, arg2[, ...]]])
    

    bind 方法 与 apply 和 call 比较类似,也能改变函数体内的 this 指向。不同的是,bind 方法的返回值是函数,并且需要稍后调用,才会执行。而 apply 和 call 则是立即调用。

    bind模拟实现

    function  myBind(context) {
      if (typeof this !== 'function') {
        throw new TypeError('Error')
      }
    const _this = this
    const args = [...arguments].slice(1)
    // 返回函数
    return function F() {
      // 1 判断是否用作构造函数
      if (this instanceof F) {
        return new _this(...args, ...arguments)
      }
      // 2 用作普通函数
      return _this.apply(context, args.concat(...arguments))
     }
    }
    

    验证一下: 普通函数

    Function.prototype.myBind = myBind
    
    var name = 'name'
    var obj = {
     name: 'objName'
    }
    
    function test(p1, p2){
      this.a = p1
      this.b = p2
      console.log(this.name,p1, p2)
    }
    var f1 = test.myBind(obj, 1)
    f1(2)//objName 1 2
    

    构造函数

    var name = 'name'
    var obj = {
     name: 'objName'
    }
    
    function test(p1, p2){
      this.a = p1
      this.b = p2
      console.log(this.name,p1, p2)//undefined 1 2
    }
    var f1 = test.myBind(obj, 1)
    var f= new f1(2)
    console.log(f)//test {a: 1, b: 2}
    

    应用场景

    1.对象的继承

    function superClass () {
        this.value = 123;
        this.print = function () {
            console.log(this.value);
        }
    }
    
    function subClass () {
        superClass.call(this);
        this.print();
    }
    
    subClass();
    //123
    

    2.借用方法

    使类数组可以使用Array 原型链上的方法

    let domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));
    

    3.Math.max||Math.min

    let arr = [1,2,3,4,5];
    console.log(Math.max.apply(this,arr))//5
    console.log(Math.min.call(this,...arr))//1
    

    4.数组合并

    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]
    

    起源地下载网 » 前端面试系列-JavaScript-call、applay、bind的区别及代码实现

    常见问题FAQ

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

    发表评论

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

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

    联系作者

    请选择支付方式

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