函数实例的 call 方法,可以指定该函数内部 this 的指向(即函数执行时所在的作用域),然后在所指定的作用域中,调用该函数。并且会立即执行该函数。
var teacher = {
name: 'up8'
}
var name = 'Felix';
person(); // Felix
person.call(); // Felix
person.call(null); // Felix
person.call(undefined); // Felix
person.call(this); // Felix
person.call(teacher); // up8
function person() {
console.log('my name is', this.name);
}
上面代码中,person 函数中的 this 关键字,如果指向全局对象,返回结果为 Felix。可以看到,如果call 方法没有参数,或者参数为 null 或 undefined 或者 this,则等同于指向全局对象。如果使用 call方法将 this 关键字指向 teacher 对象,也就是将该函数执行时所在的作用域为 teacher 对象,返回结果为 up8。
call() 方法可以传递多个参数。第一个参数是指定函数内部中 this 的指向(也就是函数执行时所在的作用域),其余参数都是函数调用时需要传递的参数。
在 《JavaScript 函数的属性和方法》 中我们聊到了
JavaScript
中所有的函数都是Function()
构造器的实例对象,并且所有函数都继承了构造器的三个方法call()
apply()
bind()
,本篇来聊一聊这三个方法。一、索源
call
,apply
,bind
这三个方法其实都是继承自Function.prototype
中的,属于实例方法。上面代码中,都返回了
true
,表明三种方法都是继承自Function.prototype
的。当然,普通的对象,函数,数组都继承了Function.prototype
对象中的三个方法,所以这三个方法都可以在对象,数组,函数中使用。二、call 方法
函数实例的
call
方法,可以指定该函数内部this
的指向(即函数执行时所在的作用域),然后在所指定的作用域中,调用该函数。并且会立即执行该函数。上面代码中,
person
函数中的this
关键字,如果指向全局对象,返回结果为Felix
。可以看到,如果call
方法没有参数,或者参数为null
或undefined
或者this
,则等同于指向全局对象。如果使用call
方法将this
关键字指向teacher
对象,也就是将该函数执行时所在的作用域为teacher
对象,返回结果为up8
。call()
方法可以传递多个参数。第一个参数是指定函数内部中this
的指向(也就是函数执行时所在的作用域),其余参数都是函数调用时需要传递的参数。第一个参数是必须的,可以是
null
,undefined
,this
,但是不能为空。设置为null
,undefined
,this
表明函数add
此时处于全局作用域。其余参数中必须一个个添加。而在apply
中必须以数组的形式添加。三、apply 方法
apply
方法的作用与call
方法类似,也是改变this
指向(函数执行时所在的作用域),然后在指定的作用域中,调用该函数。同时也会立即执行该函数。唯一的区别就是,它接收一个数组作为函数执行时的参数。apply
方法的第一个参数与call
的第一个参数一样,也是this
所要指向的那个对象,如果设为null
或undefined
或者this
,则等同于指定全局对象。第二个参数则是一个数组,该数组的所有成员依次作为参数,在调用时传入原函数。原函数的参数,在call
方法中必须一个个添加,但是在apply
方法中,必须以数组形式添加。四、bind方法
bind
方法用于指定函数内部的this
指向(执行时所在的作用域),然后返回一个新函数。bind
方法并非立即执行一个函数**上面代码中,
this.name
指向person
对象的内部属性name
, 如果把person
对象的getName
方法赋值给另外一个变量,调用执行后就不是期望的结果为什么呢?在 《JavaScript 之 this绑定/指向》 这篇文章中 提到 隐式绑定中的上下文丢失, 为了解决这个问题,可以使用
bind
方法,将person
对象里的this
绑定到person
对象上,或者是直接调用。五、实现 bind
我们来实现一个函数的
bind
方法:上面的代码,我们在
Function
构造器的原型对象中定义了一个bind
方法,然后我们定义了一个person
函数,person
函数本身没有bind
,于是使用了它的构造器的原型对象的bind
方法。再来点复杂的:
六、总结
上面的学习中,可以看出
call
,apply
,bind
三者的区别:this
的指向(函数执行时所在的作用域),然后根据指定的作用域,调用该函数。call
,bind
方法需要直接传入,而apply
方法需要以数组的形式传入。call
,apply
方法是在调用之后立即执行函数,而bind
方法没有立即执行,需要将函数再执行一遍。有点闭包的味道。this
的指向问题不仅有call
,apply
,bind
方法,也可以使用that
变量来固定this
的指向。有时候我们使用
call
或者apply
的目的不在于指定this
指向,而是另有用途,比如借用其他对象的方法,那么我们可以传入null
来代替某个具体的对象:Reference