JavaScript中this关键字详解
在JavaScript中,this
关键字用来引用当前函数的执行上下文。它可以用来引用当前正在执行的对象,这使得在函数内部可以访问该对象的属性和方法。
1. this的值
this
的值取决于它被使用的上下文。
1.1 全局上下文
在全局上下文中,this
指向全局对象。在浏览器中,这个对象就是window
对象。
console.log(this === window) // true
1.2 函数上下文
在函数内部,this
的值可以是多种不同的值,具体取决于函数被调用的方式。
1.2.1 函数作为普通函数调用
当函数作为普通函数调用时,this
指向全局对象。
function foo() {
console.log(this === window)
}
foo() // true
1.2.2 函数作为对象的方法调用
当函数作为对象的方法调用时,this
指向该对象。
var obj = {
foo: function() {
console.log(this === obj)
}
}
obj.foo() // true
1.2.3 函数作为构造函数调用
当函数作为构造函数调用时,this
指向新创建的对象。
function Foo() {
this.bar = 'baz'
}
var obj = new Foo()
console.log(obj.bar) // baz
1.2.4 函数使用apply、call或bind调用
使用apply
、call
或bind
函数调用时,this
可以被指定为任何一个对象。
function foo() {
console.log(this.name)
}
var obj1 = { name: 'object 1' }
var obj2 = { name: 'object 2' }
foo.apply(obj1) // object 1
foo.call(obj2) // object 2
foo.bind(obj1)() // object 1
1.3 箭头函数中的this
在箭头函数中,this
是在创建函数时确定的,而不是在调用函数的时候确定的。它是函数作用域内部的一个不可变值。
var obj = {
foo: () => {
console.log(this === obj)
}
}
obj.foo() // false
2. 使用this的常见问题
this
的值通常会被认为是难以理解和预测的,这是由于其值不仅仅是由其上下文决定的,还会受到很多其他因素的影响。以下是使用this
时常见的问题。
2.1 混乱的上下文
当函数执行的上下文发生变化时,this
的值也会发生变化。在使用this
时,我们需要非常小心,以确保它的值始终是我们所期望的值。
var obj = {
foo: function() {
console.log(this === obj)
}
}
var bar = obj.foo
bar() // false
2.2 使用箭头函数时没有正确地绑定this
在使用箭头函数时,我们需要非常小心,以确保它的上下文与我们所期望的一样。由于箭头函数没有自己的上下文,所以如果在箭头函数中使用了this
,它将引用其外部上下文的this
。这可能会导致意外的行为。
var obj = {
foo: () => {
console.log(this === obj)
}
}
obj.foo() // false
总结
this
是JavaScript中一个非常重要的关键字。它确定了函数被调用时的上下文,从而使函数能够引用适当的对象。在理解了this
的基本工作原理之后,我们可以更轻松地在JavaScript中编写复杂的代码。
示例1
var a = {
value: 0,
increment: function() {
this.value++
console.log(this.value)
}
}
var b = {
value: 0,
increment: a.increment
}
a.increment() // 1
b.increment() // 1
在a.increment
中,this
指向a
,a.value
被递增并输出1
。而在b.increment
中,this
指向b
,但它仍然调用了a.increment
,这意味着a.value
也被递增,输出1
。
示例2
function Counter() {
this.count = 0
setInterval(function() {
this.count++
console.log(this.count)
}, 1000)
}
var counter = new Counter()
在这个示例中,setInterval
函数中的函数被作为普通函数使用,因此它的this
指向全局对象。为了与对象实例保持一致,我们需要将this
绑定到Counter
函数的实例上。
function Counter() {
this.count = 0
setInterval(function() {
this.count++
console.log(this.count)
}.bind(this), 1000)
}
var counter = new Counter()