加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

聊聊call、apply、bind的故事

发布时间:2020-12-14 05:12:47 所属栏目:大数据 来源:网络整理
导读:说到call、apply、bind,前端的胖友可是不陌生。以下就从几个方面分别聊聊它们。 是什么?(what?) 实际上它们真正的样子是这样的: Function.prototype.call(thisArg,arg1,arg2,...) Function.prototype.apply(thisArg,[arg1,...]) Function.prototype.bind(

说到call、apply、bind,前端的胖友可是不陌生。以下就从几个方面分别聊聊它们。

是什么?(what?)

实际上它们真正的样子是这样的:

  • Function.prototype.call(thisArg,arg1,arg2,...)
  • Function.prototype.apply(thisArg,[arg1,...])
  • Function.prototype.bind(thisArg,...)

它们几个的作用都是改变this的指向。

三者有什么区别?

  • .call(thisArg,...)和.apply(thisArg,...])的区别只是后者的参数列表以数组形式传入。

  • .bind()与另外两个的区别则是前者改变this,不立即调用函数;而后者改变this,立即调用函数。

非严格模式和严格模式的注意点

以下例子在非严格模式下,

// 注释的是各个情况this的指向
let test = {
    foo: function(...arg) {
        console.log(this);
        console.log([...arg]);
    }
}
test.foo();
test.foo.call(null,1,2);//this->window
test.foo.call(‘‘,2);// this->string
test.foo.call(undefined,2); //this->window
test.foo.apply(null,[1,2]);//this->window
test.foo.apply(‘‘,2]);// this->string
test.foo.apply(undefined,2]);//this->window
test.foo.bind(null,2);
test.foo.bind(‘‘,2);
test.foo.bind(undefined,2);

在严格模式下,

// 注释的是各个情况this的指向
‘use strict‘
let test = {
    foo: function(...arg) {
        console.log(this);
        console.log([...arg]);
    }
}
test.foo();
test.foo.call(null,2);//this->null
test.foo.call(‘‘,2);// this->
test.foo.call(undefined,2); //this->undefined
test.foo.apply(null,2]);//this->null
test.foo.apply(‘‘,2]);//this->
test.foo.apply(undefined,2]);// this->undefined
test.foo.bind(null,2);

怎么模拟实现三者呢?

那么为什么要模拟实现呢?

  • 更加理解三者改变this指向的原理
  • 兼容一些浏览器
.mycall()的实现
Function.prototype.mycall = function(context,...arg) {
      // 改变this指向
      // 1. 通过this获取函数,
      var context = context || window;
      context.fn = this;
      // 执行函数
      context.fn(...arg);
      // 2. 删除函数
      delete context.fn;      
    }
    var foo = {
      value: ‘foo‘
    }
    var bar = function(name,age) {
      console.log(name);
      console.log(age);
      console.log(this.value);
      console.log(this);
    }
    // bar.mycall(foo,‘zenquan‘,23);
    bar.mycall(null,23)
.myapply()的实现
Function.prototype.myapply= function(context,[...arg]) {
      // 改变this指向
      // 1. 通过this获取函数,
      var context = Object(context) || window;
      context.fn = this;
      var result = null;
      // 执行函数
      if(![...arg]) {
        result = context.fn();
      }else {
        result = context.fn(...arg);
      }
      // 2. 删除函数
      delete context.fn;  
      return result;    
    }
var bar = function(name,age) {
      console.log(name);
      console.log(age);
      // console.log(this.value);
      console.log(this);
    }
    bar.myapply(null,[‘zenquan‘,23]);
.mybind()的实现
Function.prototype.mybind = function (context) {

    if (typeof this !== "function") {
      throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
    }

    var self = this;
    var args = Array.prototype.slice.call(arguments,1);

    var fNOP = function () {};

    var fBound = function () {
        var bindArgs = Array.prototype.slice.call(arguments);
        return self.apply(this instanceof fNOP ? this : context,args.concat(bindArgs));
    }

    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();
    return fBound;
}

Emmm,说好了聊聊故事,结果还是说了一大堆干巴巴的知识,可能我是个不会讲故事的标题党吧。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读