JS面试题之手写一个call方法

说明

首先,call方法是JS function中内置的一个方法,主要的作用有两个:

  • 改变函数的this指向
  • 向函数中传递参数

使用方式如下:

fn.call(obj, 100, 200)

接下来通过封装来实现一下call方法。

实现

首先,为了让每个函数的身上都能使用call方法,可以把call方法绑定到Function的原型上。

Function.prototype.myCall = function() {}

这样,就可以在每个函数的身上都能使用到myCall方法。

例如:

demoFn.myCall()

在myCall方法中,默认的this指向未来的实例化对象,也就是myCall方法的调用者(这里指的是要改变this指向的普通函数)。

为了一会方便调用,这里先把this进行存储。

Function.prototype.myCall = function() {
	var that = this
}

因为call方法允许传递最少两个,最多n个参数,第一个参数表示this的新指向,后续的参数表示的是传递到函数内部的参数值,这里在myCall方法中为了可以符合call方法的使用方式,需要通过arguments对象来进行模拟。

 var that = this // 这里将this存储起来
 var obj = Array.from(arguments)[0] // obj存储的是改变之后的this新的指向
 var args = Array.from(arguments).slice(1) // args存储的是传递过来的参数

同时,call方法还有一个特性,就是调用之后会立刻执行函数,所以这里我们可以把前面存储到that变量中的实例对象函数临时赋值给传递过来的新的对象,然后在其身上调用,调用完成后删除即可。

obj.temp_f = that

var res = obj.temp_f(...args)
// 在得到返回值之后,将对象身上的这个临时方法删除掉
delete obj.temp_f
return res

不要忘了给函数传递参数以及将返回值返回。

完整代码:

// 1. 首先,call方法属于Function构造函数原型上的方法
// 2. 需要传递最少两个参数,第一个参数是this指向,可能值是新的对象或者null ,第二个参数以及之后是传递的参数
Function.prototype.myCall = function() {
  // 此时在myCall内部,this指向调用者fn
  var that = this // 这里将this存储起来
  var obj = Array.from(arguments)[0] // obj存储的是改变之后的this新的指向
  var args = Array.from(arguments).slice(1) // args存储的是传递过来的参数
  // 接下来把之前的需要改变this指向的函数存储到新的this对象上,并且把参数传递进去
  obj.temp_f = that

  var res = obj.temp_f(...args)
  // 在得到返回值之后,将对象身上的这个临时方法删除掉
  delete obj.temp_f
  return res
}

// 测试代码
var obj = { user: 'zs' }

function fn1(a,b) {
  console.log(this.user)
  console.log(a,b)
}

fn1.myCall(obj, 100, 200)

你可能感兴趣的:(前端,面试题,javascript,前端,原型模式)