call&apply&bind小结

一、方法定义

call方法

语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]])

定义:调用一个对象的一个方法,以另一个对象替换当前对象。

说明:call方法可以用来代替另一个对象调用一个方法。call方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。 arg1 … argN为被调用方法的传参。

function numAdd( a, b ) {
    console.log(this);
    console.log(a + b, "123456");
}

function numPow( a, b ) {
    console.log(this);
    console.log(Math.pow(a, b), "xxxxxx")
}

//把numAdd方法放在numPow上执行
//this指向numPow
numAdd.call(numPow, 3, 4);          // 7
//把numPow方法放在numAdd上执行
//this指向numAdd
numPow.call(numAdd, 3, 4);          // 81

Object.prototype.toString.call(numAdd)


apply方法

语法:apply([thisObj[,argArray]])

定义:应用某一对象的一个方法,用另一个对象替换当前对象。

说明:apply的第一个参数thisObj和call方法的一样,第二个参数argArray为一个传参数组。thisObj如果未传,那么 Global 对象被用作 thisObj。

function add( a, b ) {
    console.log(this);
    console.log(a + b, "123456");
}

function pow( a, b ) {
    console.log(this);
    console.log(Math.pow(a, b), "xxxxxx")
}

//把numAdd方法放在numPow上执行
//this指向pow
add.apply(pow, [ 3, 4 ]);;          // 7
//把numPow方法放在numAdd上执行
//this指向add
pow.apply(add, [ 3, 4 ]);          // 81

bind方法 ECMAScript5中扩展了叫bind的方法(IE6,7,8不支持)

语法:bind([thisObj[,arg1[, arg2[, [,.argN]]]]])

定义:应用某一对象的一个方法,用另一个对象替换当前对象。

说明:bind的thisObj参数也和call方法一样,thisObj如果未传,那么 Global 对象被用作 thisObj。arg1 … argN可传可不传。如果不传,可以在调用的时候再传。如果传了,调用的时候则可以不传,调用的时候如果你还是传了,则不生效。

function add( a, b ) {
    console.log(this);
    console.log(a + b, "123456");
}

function pow( a, b ) {
    console.log(this);
    console.log(Math.pow(a, b), "xxxxxx")
}

//把add方法放在pow上执行
//this指向pow
aadd.bind(pow)( 3, 4);          // 7
//把pow方法放在add上执行
//this指向add
pow.bind(add)( 3, 4);          // 81

二、call,apply,bind的相似

  1. 都是用来改变函数this指向的

  2. 第一个参数都是this要指向的对象

  3. 都可以传参

三、call,apply,bind的区别

  1. callapply都是对函数的直接调用

  2. bind返回的是一个函数,需要配合()进行调用

  3. callbind的传参使用,分隔的 例如(item1,item2,item3...)

  4. apply的传参使用数组[...arguments]

四、简单实现call

Function.prototype.selfCallWithEs5 = function (context) {
  var context = context || window;
  context.fn = this;
  var args = [];
  for (var i = 1; i < arguments.length; i++) {
    args.push("arguments[" + i + "]");
  }
  args = args.join(",");

  var result = eval("context.fn(" + args + ")");

  delete context.fn;
  return result; //因为有可能this函数会有返回值return
}

Function.prototype.selfCallWithEs6 = function (context, ...args) {
  context = context || window;
  context.fn = this;
  const result = context.fn(...args);
  delete context.fn;
  return result;
};

五、简单实现apply

Function.prototype.selfApplyWithEs5 = function (context, arr) {
  var context = context || window;
  context.fn = this;
  var args = [];
  var params = arr || [];
  for (var i = 0; i < params.length; i++) {
    args.push("params[" + i + "]");
  }
  args = args.join(",");
  var result = eval("context.fn(" + args + ")");

  delete context.fn;
  return result; //因为有可能this函数会有返回值return
}

Function.prototype.selfApplyWithEs6 = function(context, arr) {
  context = context || window;
  context.fn = this;
  arr = arr || [];
  const result = context.fn(...arr);
  delete context.fn;
  return result;
}

六、简单实现bind

Function.prototype.selfBindWithEs5 = function (context) {
  var _this = this;
  var argsParent = Array.prototype.slice.call(arguments, 1);
  return function () {
    var args = argsParent.concat(Array.prototype.slice.call(arguments)); //转化成数组
    _this.apply(context, args);
  };
}

Function.prototype.selfBindWithEs6 = function (context) {
  var fn = this;
  var argsParent = [...arguments];
  return function () {
    fn.call(...argsParent, ...arguments);
  };
}
原文链接:juejin.im

上一篇:小程序中switch case如何优化
下一篇:如何实现最真实的web打印

相关推荐

  • 🔥 Promise|async|Generator 实现&amp;原理大解析 | 9k字

    笔者刚接触async/await时,就被其暂停执行的特性吸引了,心想在没有原生API支持的情况下,await居然能挂起当前方法,实现暂停执行,我感到十分好奇。好奇心驱使我一层一层剥开有关JS异步编程的...

    9 天前
  • 高阶函数&amp;&amp;高阶组件

    高阶函数 特点: 接受函数类型的参数。 返回值是函数。 高阶函数具有可扩展性。 常见的高阶函数: 定时器 setTimeout(); setInterval() Promise(); 数组相关:...

    25 天前
  • 面试常谈之手写new、call、apply和bind

    new 可以概括为以下四步: 1.创建一个空对象 2.链接到原型 3.绑定this值 4.返回新对象 call 这里提供两种写法 本文参考: (https://www.ji...

    7 个月前
  • 面试官:bind两次的结果了解一下

    背景 最近帮助组内进行技术面试,听到有人问了个很有意思的问题,函数bind两次后this指向。平时使用和问的比较多的都是bind接收的参数和bind后的this指向问题,bind多次还真没去想过。

    3 个月前
  • 面试官问:能否模拟实现bind

    前言 用过的同学都知道,经常会使用来绑定。 那么面试官可能会问是否想过到底做了什么,怎么模拟实现呢。 附上之前写文章写过的一段话:已经有很多模拟实现的文章,为什么自己还要写一遍呢。

    1 年前
  • 面试官问:能否模拟实现JS的call和apply方法

    之前写过两篇《面试官问:能否模拟实现的操作符》(https://juejin.im/post/5bde7c926fb9a049f66b8b52)和《面试官问:能否模拟实现的方法》(https://ju...

    1 年前
  • 面试官:你能手写实现call,apply,bind方法吗?

    实践系列 主要是让我们通过实践去加深对一些原理的理解。 实践系列前端路由(https://juejin.im/post/5c380afde51d4552232fb077) 实践系列Babel原理(...

    1 年前
  • 需要说明的_功能。bindall() Underscore.js

    ThiefMasterNik So(https://stackoverflow.com/users/298479/thiefmaster)提出了一个问题:need explanation of the...

    2 年前
  • 重磅宣布, concent 2.0发布, 依赖收集&amp;惰性计算

    夜已经很深了,这个时间宣布2.0版本算是一个抢先预告吧,接下来的一个月里会重点开始更新文档以及铺开更多的示例了。 两个版本的差异 1. 版本为了尽量向上兼容古老的浏览器,没有使用任何新的es特性,但是...

    22 天前
  • 都2020年了,你应该知道如何手写Call、Apply、Bind了吧

    导读 作为面试中面试官最宠爱的一个问题,在这里进行一个详细的介绍,大家重点要放在理解,而不是背。 写的不好或不对的地方,请大家积极指出,好了,话不多说,我们“圆规正转” 一、手写实现Call ...

    3 个月前

官方社区

扫码加入 JavaScript 社区