美文网首页
bind & apply & call 的使用及简单实现

bind & apply & call 的使用及简单实现

作者: kevin5979 | 来源:发表于2021-02-04 09:38 被阅读0次

三个方法的比较

相同点

  • 都是属于Function.prototype对象下的方法
  • 都是为改变this指向而存在的
    异同点
  • 使用call()方法时,传递给函数的参数必须逐个列举出来,
  • 使用apply()方法时,传递给函数的是参数数组。
  • bind()call()很相似,第一个参数是this的指向,从第二个参数开始是接收的参数列表。
  • bind() 方法不会立即执行,而是返回一个改变了上下文 this后的函数,用于稍后调用。
  • call()apply()则是立即调用。

没有绑定this
function getProfile(name, age) {
  console.log(this);   // window
  console.log(name, age);  // tom, 18
}
getProfile("tom", 18);
绑定this
function getProfile(name, age) {
  console.log(this);   // {name: "kevin", age: 20}
  console.log(name, age);  // tom, 18
}
let obj = {
  name: 'kevin',
  age: 20
}
let foo = getProfile.bind(obj, 'tom', 18);  // bind绑定
foo();
getProfile.call(obj, "tom", 18);  // call绑定
getProfile.apply(obj, ["tom", 18]);  // apply绑定

bind 实现
  • 改变this指向,返回一个新函数
Function.prototype.bind = function (context) {
  let self = this;
  return function () {
    self.apply(context, Array.prototype.slice.call(arguments, 1))
  }
}
call 实现
  • 改变this指向,返回函数执行结果
Function.prototype.call = function () {
  let ctx = arguments[0] || window;  // 保存执行上下文(绑定的this)
  ctx.fn = this;  // 保存执行函数
  let args = [];
  for (var i = 1; i < arguments.length; i++) {
    args.push(`arguments[${i}]`);  // 保存执行参数
  }
  let result = eval(`ctx.fn(${args.join(',')})`);  // 获取结果
  delete ctx.fn;  // 删除函数
  return result;  // 返回结果
}
apply 实现
  • 改变this指向,返回函数执行结果
Function.prototype.apply = function (ctx, arr) {
  let ctx = ctx || window;  // 保存执行上下文(绑定的this)
  ctx.fn = this;  // 保存执行函数
  if (!arr) {  // 没有参数 
    let result = ctx.fn();  // 执行函数
    delete ctx.fn;  // 删除函数
    return result;  // 返回结果
  } else {
    let args = [];
    for (let i = 0; i < arr.length; i++) {
      args.push(`arr[${i}]`);  // 保存参数
    }
    let result = eval(`ctx.fn(${args.join(',')})`);  // 执行函数
    delete ctx.fn;  // 删除函数
    return result;  // 返回结果
  }
}
END

相关文章

网友评论

      本文标题:bind & apply & call 的使用及简单实现

      本文链接:https://www.haomeiwen.com/subject/nbdytltx.html