每个javascript
函数都有两个非继承的方法 apply()
、 call()
,这两个方法的用途相同,都是在特定的作用域中调用函数,直接一点的说法就是改变函数内部的this
指针。
this指针介绍
this
表示当前对象的一个引用。
单独使用this
时,this
默认指向全局对象window
。(当前对象是window
对象)
console.log(this) // 打印window对象
当在浏览器中全局运行函数时,它的this
指针同样默认指向全局对象window
。(当前对象是window
对象)
function fun() {
console.log(this) // 打印window对象
}
当在对象里的方法使用this
指针的时候,它指向当前对象。(当前对象是obj对象)
var obj = {
title: 'fun',
fun: function() {
console.log(this) // 打印obj对象
}
}
使用apply()方法
apply()
方法接受两个参数,第一个参数是在其中运行函数的作用域,第二个参数是是一个参数数组,用于向函数中传递参数。
var num = 10
function myFun1(num1, num2) {
console.log(this.num + num1 + num2)
}
myFun1(1,2)
上面的代码定义了全局变量num
和全局函数myFun
,当运行myFun
函数时,将会打印10 + 1 + 2
的值,也就是13
。
var num = 10
var myObj = {
num: 20,
myFun2: function(num1, num2) {
console.log(this.num + num1 + num2)
}
}
myObj.myFun2(1,2)
上面这串代码,将变量和方法都定义在一个对象里,这样this.num
不再是全局的num
,而是当前对象中的num
,所以结果打印出来的是20 + 1 + 2
的值,也就是23
。 如果我想在运行myFun1
时能够使用myObj
中的num
怎么办?这里就可以使用apply
函数来改变this
指向。
myFun1.apply(myObj, [1, 2])
使用上面这串代码最终将打印23
,说明已经改变了myFun1
的this
指向。其中的this.num
是20
。 同样的,也可以在运行myFun2
的时候使用全局的变量num
,只需要将this
指向全局对象window
就行。
myObj.myFun2.apply(window, [1, 2])
最终打印的结果是13
,说明这里的this.num
是10
。 上面的代码apply
函数传参使用参数数组,也就是[1, 2]
的形式,分别代表第一第二个参数,如果函数不需要传参数,可以不传apply
的第二个参数。
使用call()方法,它与apply()有什么不同?
call
函数的使用方法基本上和apply
一样,只是传递参数的方式不一样
,apply
通过参数数组的形式传参,而call
需要把参数一个个都分别传进去。例如将上面的例子改成使用call
函数,如下:
myFun1.call(myObj, 1, 2)
使用bind()函数绑定this指针
bind
方法同样用于改变this
指针,但和apply
、call
方法不同。apply
和call
在调用函数后会立即执行,不会保存this
改变后的状态。而bind
在调用函数后不会立即执行,在改变this
指针后返回一个新的函数,供以后使用。
myFun1.apply(myObj, [1, 2]) // 23
myFun1(1, 2) // 13
上面的例子中,在myFun1
执行apply
函数后,其本身并没有改变this
指向,在下次执行时还是会变回原来的this
。如果想保存this
改变后的状态,就需要使用bind
函数。
var myFun3 = myFun1.bind(myObj)
myFun3(1, 2) // 23
myFun3(1, 2) // 23