手写call,apply

call

传入一个指定的对象和若干指定的参数的前提下调用指定对象的属性和方法

var obj = {
  name : 'harry'
}

function getName () {
  console.log(this.name);
}

getName.call(obj) //harry

模拟实现,第一步

  • 给对象添加方法
  • 执行方法
  • 删除方法
//以上代码相当于给obj添加了getName方法并调用它
var obj = {
  name : 'harry',
  getName: function () {
    console.log(this.name);
  }
}

obj.getName() //harry
//但同时给obj添加了一个属性方法,我们可以删除它
delete obj.getName
Function.prototype.myCall = function (context) {
  //判断有没有传入context,如果没有就将其设为window
  var context = context || window
  context.fn = this
  context.fn()
  delete context.fn
}

第二步,call还可以传入不定数目的参数

  • 从 Arguments 对象中取值,取出第二个到最后一个参数,然后放到一个数组里
  • 使用slice方法,获取参数
Function.prototype.myCall = function (context) {
  //判断有没有传入context,如果没有就将其设为window
  var context = context || window
  context.fn = this
  let args = [...arguments].slice(1)
  context.fn(...args)
  delete context.fn
}

第三步,call可以有返回值

var obj = {
  value: 1
}

function bar(name) {
  console.log(this.value);
  return {
    value : this.value,
    name
  }
}

let res = bar.call(obj, 'harry')

console.log(res); //{value: 1, name: 'harry'}

补全代码

Function.prototype.myCall = function (context) {
  //判断有没有传入context,如果没有就将其设为window
  var context = context || window
  context.fn = this
  let args = [...arguments].slice(1),
      res = null
  res = context.fn(...args)
  delete context.fn
  return res
}

测试代码

var foo = {
  value : 1,
  
}

function bar (name, age) {
  this.name = name
  this.age = age
  console.log(this.value);
  console.log(`我是${this.name},我${this.age}岁了`);
}


Function.prototype.myCall = function (context) {
  var context = context || window
  context.fn = this
  let args = [...arguments].slice(1),
      res = null

  res = eval(context.fn(...args))
  delete context.fn
  return res
}

let res = bar.myCall(foo, 'potter', 12) //1 我是potter,我12岁了

apply

apply和call相似,apply参数接受一个指定的对象和数组

Function.prototype.myApply = function (context) {
  //判断有没有传入context,如果没有就将其设为window
  var context = context || window
  context.fn = this
//判断有没有传入第二个参数数组
  if (arguments[1]) {
    res = context.fn(...arguments[1])
  } else {
    res = context.fn()
  }
  delete context.fn
  return res
}


var obj = {
  value : 1
}

function bar (name, age) {
  this.name = name
  this.age = age
  console.log(this.value);
  console.log(`我是${this.name},我${this.age}岁了`);
}

bar.apply(obj, ['potter', 13])
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容