this
首先,this指向在函数定义的时候是确定不了的,只有在函数执行的时候才能确定this到底指向谁,实际上this最终指向的是它的调用者
实例1:
function a(){
console.log('test') // test
console.log('this',this)
}
a()
输出效果:
对于一般的函数,它的this都指向window。因为创建的普通函数,实际上都只是在给window添加一个属性。所以他们的调用者都是指window。
实例2:
let obj = {
test: 'test', //test
a: function() {
console.log('this:',this)
}
}
console.log('obj.test:',obj.test)
obj.a()
console.log('obj:',obj)
输出效果:
在这个例子中,可以清楚的看到函数a中的this指向了函数的调用者obj。
实例3:
let obj = {
test1: 'test1',
str :{
test2: 'test2',
a: function(){
console.log('this:',this)
}
}
}
obj.str.a()
console.log('obj.str:',obj.str)
console.log('obj:',obj)
输出效果:
在这个例子中可以清楚的看到,虽然函数a的最终调用者是 obj,但是它的this却指向的 obj.str。此时的函数a是obj.str的一个属性。
所以,通过上述例子可以得知,函数具体作为一个属性添加给了某一个对象,那么该对象就是函数的this指向
call,apply,bind
call() , apply() , bind() 这几个函数都可以改变 this 的指向
实例1:
let obj = {
test: 'test',
a : function() {
console.log('this.test:',this.test)
}
}
let str = obj.a
obj.a() // this.test: test
str() // this.test: undefined
str.call(obj) // this.test: test
输出效果:
在该例子中,str() 输出的是 this.test: undefined ,是因为str现在是作为一个函数,在调用时,是作为window的一个属性被调用,因此它的this指向是window。而window中没有test这个属性,所以str()输出就是 undefined
当使用了 call() 时,call将str的this指向改变成了obj,而obj中有test属性,所以会输出 test
在call中,还可以给函数传参
let obj = {
test: 'test',
a : function(a,b) {
console.log('this.test:',this.test)
console.log('a = ',a, ' b = ',b)
}
}
let str = obj.a
str.call(obj,1,2)
输出效果:
实例2:
let obj = {
test: 'test',
a : function() {
console.log('this.test:',this.test)
}
}
let str = obj.a
obj.a() // this.test: test
str() // this.test: undefined
str.apply(obj) // this.test: test
输出效果:
当使用了 apply() 时,apply将str的this指向改变成了obj,而obj中有test属性,所以会输出 test
apply()以数组形式给函数传参
let obj = {
test: 'test',
a : function(a,b) {
console.log('this.test:',this.test)
console.log('a = ',a, ' b = ',b)
}
}
let str = obj.a
str.apply(obj,[1,3])
输出效果:
实例3:
let obj = {
test: 'test',
a : function() {
console.log('this.test:',this.test)
}
}
let str = obj.a
obj.a() // this.test: test
str() // this.test: undefined
let str1 = str.bind(obj)
str1() // this.test: test
输出效果:
当使用了 bind() 时,bind将str的this指向改变成了obj。但是bind方法只是返回一个修改了this指向后的新函数,所以需要对新函数进行调用
bind给函数传参
let obj = {
test: 'test',
a : function(a,b) {
console.log('this.test:',this.test)
console.log('a = ',a, ' b = ',b)
}
}
let str = obj.a
let str1 = str.bind(obj)
str1(1,2)
输出效果:
总结:call,apply,bind这三个函数都可以改变this指向;
但是,call 和 apply 在改变函数的this指向时,就立即执行该函数,而bind是返回一个改变this指向后的新函数,需要重新调用新函数,才能执行;
call 和 bind 的传参方式方式相同,而 apply 是使用数组方式传参