apply面试题引发的思考

236 阅读2分钟

apply

一道有意思的面试题

## 方法重用

通过 apply() 方法,您能够编写用于不同对象的方法。

apply函数在前端的世界里大家都耳熟能祥了

关于apply碰到了一道有意思的面试题记录下来。

我们先来看看这段代码:

function fn () {
    console.log('hello this is apply)
}

fn.apply = function () {
    console.log('调用apply')
}

上边这段代码当我们需要使用fn.apply的时候,想修改fnthis指向,应该如何做呢?

当我们平平常常(tianzhen)的来调用一下它的apply

fn.apply(null)

// 打印:调用apply

打印结果是调用apply,这个时候我们已经重写了fn上的apply方法,再次调用apply肯定调用的事我们重写后的apply函数,这个时候就犯了难了,我就是想要在这个情况下调用fn原本的apply函数,我们应该怎么做?

别着急往下看,尝试思考思考。


解决方式

基于原型思路方式

其实有两种解决方式,我们先来看看第一种。

有的同学可能已经猜到了,apply本质上是挂在Function.prototype上的方法。既然我们重写了函数本身的apply,而fnapply也是通过原型去查找的。所以我们可以通过Function.prototype.apply获得fn函数原本的apply方法。

这个时候我们需要调用它就很简单了

Function.prototype.apply.call(fn,null,[1,2,3])
  • 第一个参数fn,是我们传递给方法Function.prototype.applythis。这样的话就相当于fn.apply(此时的apply是原型上的apply方法)。

  • 第二个参数null,是call方法传递给apply方法的第一个参数,也就是规定的this指向。

  • 第三个参数是一个数组,是传递给apply方法的参数。

这样就可以通过原型的方式调用fn函数的apply方法,并且支持自定义this指向和传入指定参数。

Reflect

当然在Es6中有一种更简单的方式,就是直接使用Reflect.apply(fn)就可以直接达到想要的效果。

Reflect.apply(target, thisArgument, argumentsList)

Reflect.apply()

参数

  • target

    目标函数。

  • thisArgument

    target函数调用时绑定的this对象。

  • argumentsList

    target函数调用时传入的实参列表,该参数应该是一个类数组的对象。

Reflect.apply(fn, null, [1, 2, 3]);