this
this
关键字,就是所谓的执行上下文。this
关键字在函数中,表示的是一个指向,this
的指向永远是一个对象。
哪个对象调用函数,函数里面的this指向哪个对象。
代码示例:
function f() {
let text="哈哈哈"
console.log(this.text) // undefined
console.log(this) // Window
}
f()
上面的代码等价于:
function f() {
let text="哈哈哈"
console.log(this.text) // undefined
console.log(this) // Window
}
window.f()
f()
函数实际上是被window
对象调用的
var o = {
text:'呵呵',
f:function(){
console.log(this.text) // 呵呵
console.log(this) // {text: "呵呵", f: ƒ}
}
}
o.f()
这里this
指向对象o
,因为是对象o
调用f()
上面代码等价于:
var o = {
text:'呵呵',
f:function(){
console.log(this.text) // 呵呵
console.log(this) // {text: "呵呵", f: ƒ}
}
}
window.o.f()
由此可以看出this指向的是最后调用它的对象
下面再来看看这个:
var o = {
text:'呵呵',
a:{
text:'嘿嘿',
f:function(){
console.log(this.text) // undefined
console.log(this) // Window
}
}
}
var fun = o.a.f
fun()
上面this
指向window
, 最下面的fun()
等价于window.fun()
。而this
指向的是最后调用它的对象
function f(){
this.text="呵呵"
}
var o = new f()
console.log(o.text) // 呵呵
console.log(o) // f {text: "呵呵"}
上面,new
关键字创建了一个对象实例o
。new
关键字会改变this
的指向,这个时候指向对象o
假如,函数里有return
,this
指向会怎样?
function f() {
this.text="呵呵"
return {}
}
var o = new f
console.log(o.text) // undefined
onsole.log(o) // {}
function f() {
this.text="呵呵"
return function(){};
}
var o = new f
console.log(o.text) // undefined
console.log(o) // ƒ (){}
function f() {
this.text="呵呵"
return 1
}
var o = new f
console.log(o.text) // 呵呵
console.log(o) // f {text: "呵呵"}
function f() {
this.text="呵呵"
return null
}
var o = new f
console.log(o.text) // 呵呵
console.log(o) // f {text: "呵呵"}
由以上代码可知:
如果返回值是一个对象,this指向这个返回的对象;
如果返回值不是一个对象,this还是指向函数的实例
注意: 虽然null也是对象,但它比较特殊,this指向的是函数的实例
匿名函数的this
指向问题:
var o = {
text:'呵呵',
f:function(){
return function(){
console.log(this.text) // undefined
console.log(this) // Window
}
}
}
o.f()()
上面,f
方法return
了一个匿名函数,这个匿名函数中的this
指向window
关于setInterval
和setTimeout
中的this
指向问题
const people = {
name: '小白',
sayHi() {
// this 即当前对象
console.log(this)
},
wait() {
setTimeout(function() {
// this === window
console.log(this)
})
}
}
people.sayHi() // {name: "小白", sayHi: ƒ, wait: ƒ}
people.wait() // Window
从上面可以看出,setTimeout
中的this
指向了window
对象。
这是因为setTimeout()
调用的代码运行在与所在函数完全分离的执行环境上。这会导致这些代码中包含的 this
关键字会指向 window
对象
箭头函数
箭头函数的this 是取上级作用域的值
箭头函数的this
定义:箭头函数的this
是在定义函数时绑定的,不是在执行过程中绑定的。简单的说,函数在定义时,this
就继承了定义函数的对象。
const people = {
name: '小白',
sayHi() {
// this 即当前对象
console.log(this)
},
wait() {
// 箭头函数的this 是取上级作用域的值
setTimeout(() => {
// this === 即当前对象
console.log(this)
})
}
}
people.sayHi() // {name: "小白", sayHi: ƒ, wait: ƒ}
people.wait() // {name: "小白", sayHi: ƒ, wait: ƒ}
如果想改变this的指向,可以使用:call()
apply()
bind()
fn.call(this, p1, p2, p3)
fn.apply(this, arguments)
var fn1 = fn.bind(this, p1, p2, p3)
fn1()
相同点:
- 改变对象的执行上下文(总的来说,就是改变
this
的指向) - 都可以指定调用实参。
不同点:
call()
和bind()
的参数是直接连续传递,而apply
传递参数是以一个数组传递bind()
会返回一个方法。