每个函数都包含两个非继承而来的方法:apply()与call()。

这两个方法除了接收的参数不同,功能上相差无几,二者用途皆为在某作用域中调用函数,修改函数体内的this指向。


用例子通俗易懂的解释:

window.color = 'red'
let obj = {color: 'blue'}
function ff() {
    console.log(this)
    return this.color
}

我们在全局中定义一个color和一个对象,一个函数。


直接执行 ff() 函数:

因为是在全局中调用,所以this指向全局,打印的值为:red。

使用 ff.apply(obj)

此时的this指向obj对象,所以打印的值为:blue。

QQ图片20191105151815.png


使用 ff.call(obj):

与apply一样,this指向obj对象,打印的值为:blue。

QQ图片20191105151815.png


我们可以看到,二者在不传参的情况下,作用一致,接下来我们看一下传参各自的表现.

修改一下代码,打印接收到arguments
window.color = 'red'
let obj = {color: 'blue'}
function ff() {
    console.log('arguments.length',arguments.length)
    console.log(arguments)
    return this.color
}

使用 ff.apply(obj,['one','two','three'])

我们可以的看到,传入的参数是一个具有三个项的数组,但是打印出来的是三个分开单独参数,且arguments的长度也为3。

11.png

传入非数组参数apply会报错,因为只能接收数组或类数组对象。
ff.apply(obj,'one')

44.png


使用 ff.call(obj,['one','two','three']):

使用call()和apply的不同点是,传入的是一个数组,打印出来的参数也就是一个数组,rguments的长度为1。

22.png

如果我们想让其分别传递,就只能将参数分开传递:ff.call(obj,'one','two','three')

33.png


总结
二者在功能上并无差异,仅仅只是在处理传递进来的参数上有所区别,何时使用apply何时使用call,完全取决于使用场景,如果我们想要传入数组参数或者arguments,apply更方便,否则就是call方便,但是我们要记得,apply只能接收数组或arguments,call是其他类型都能接收。


大表哥
29 声望1 粉丝