面向对象语言中,this表示当前对象的一个引用。 但在 JavaScript 中 this 不是固定不变的,它会随着执行环境的改变而改变。
1.普通调用和全局环境下
this指向全局对象。浏览器是window,node环境中时global。
function fun(){
console.log(this) //window或者global
}
fun()
console.log(this) //window或者global
2.严格模式
严格模式下,全局作用域中的this指向全局对象。函数普通调用指向undefined。
"use strict";
console.log(this) // window或者global
function fun() {
console.log(this) // undefined
}
fun()
function f1() {
function f2() {
console.log(this) // undefined
}
f2()
fun()
}
f1()
3.对象调用
以对象(方法)的方式调用时,this指向调用该函数的对象
let obj = {
name: "obj",
fun: function () {
console.log(this.name) // obj
},
childObj: {
name:"childObj",
f2: function () {
console.log(this.name) // childObj
}
}
}
obj.fun()
obj.childObj.f2()
4.构造函数
此时,this指向实例对象。
function Fun(name){
this.name = name
console.log(this) // obj
}
let obj = new Fun("obj")
5.事件处理函数
this指向事件源。
<button id="btn" onclick="alert(this)">按钮</button><!-- btn -->
<script>
let btn = document.querySelector("#btn")
btn.onclick = function () {
console.log(this) // btn
}
btn.addEventListener("click", function () {
console.log(this) // btn
})
</script>
6.定时器回调函数
this指向全局对象。
setTimeout(function () {
console.log(this) // window或者global
}, 1000)
7.箭头函数
箭头函数本身没有this,挡在箭头函数中使用this时,会指向父级作用域的this。
let obj = {
fun: () => {
console.log(this) // window或者global
}
}
obj.fun()
8.改变this指向
js中有三个方法可以改变this指向,他们分别是call,apply和bind
1.call
原函数.call方法的第一个参数是新的this指向。从第二个参数开始往后,是依次传递给原函数的参数。并且在调用call方法后,这个改变了this指向的新函数会立即执行。
let sxl = { name: "sxl" }
function fun(c1, c2) {
console.log(this.name) // sxl
console.log(c1) // 1
console.log(c2) // 2
}
fun.call(sxl, 1, 2)
2.apply
和call不同的是,apply只有两个参数。第一个参数是新的this指向。第二个参数是一个数组,数组中的每一项是依次传递给原函数的参数。执行时机和call一样,会立即执行。
let sxl = { name: "sxl" }
function fun(c1, c2) {
console.log(this.name) // sxl
console.log(c1) // 1
console.log(c2) // 2
}
fun.apply(sxl, [1, 2])
/* Math.max使用apply求最大值 */
let arr = [1, 2, 3, 4, 5]
console.log(Math.max.apply(null, arr)) // 5
3.bind
bind方法和call的参数是一样的,第一个参数是新的this指向。从第二个参数开始往后,依次是传递给原函数的参数。bind和call不同的是不会立即执行,而是返回一个改变了this指向新函数, 需要显性调用了才会执行。
let sxl = { name: "sxl" }
function fun(c1, c2) {
console.log(this.name) // sxl
console.log(c1) // 1
console.log(c2) // 2
}
let newFun = fun.bind(sxl, 1, 2)
/* 需要显性调用 */
newFun()