this指向
1、全局作用域下 window
console.log(this) //window
2、普通函数 window
function fn() {
console.log(this) //window
}
fn()
3、立即执行函数IIFE window
// IIFE(立即执行函数)->window (其实就相当于被调用的普通函数)
(function () { console.log(this) })() // window
(function () { console.log(this) }()) // window
4、严格模式,全局作用域中的 this
指向 undefined
function fn() {
'use strict'
console.log(this) // 函数内部开启严格模式, this指向undefined
}
fn()
5、对象中的方法中的this谁调用指向谁(指向调用它的这个对象)
let obj = {
name: '张三',
speak: function () {
console.log(this)
}
}
obj.speak() // obj
6、注册事件,指向事件源(给谁注册的事件就指向谁)
<button>按钮</button>
<script>
let btn = document.querySelector('button')
btn.onclick = function () {
console.log(this) // btn
}
</script>
7、定时器里面的回调函数this指向window
// 当定时器结束后,里面的回调函数被当作普通函数使用,所以this指向window
setTimeout(function(){
console.log(this) // window
},1000)
8、箭头函数没有this,它内部this由所处作用域(上下文)决定,call/apply/bind
也不能改变箭头函数this
const obj = {
value: 10,
getValue: function () {
// 传统函数
function normalFunction() {
console.log(this) // window (这里的 this 指向全局对象(在浏览器中是 window),因为 // normalFunction 是作为一个普通函数调用,而不是 obj 的方法)
}
// 箭头函数
const arrowFunction = () => {
console.log(this) // obj(这里的 this 指向 obj,因为箭头函数捕获了定义时的上下文(即 obj 的方法 // getValue
}
normalFunction()
arrowFunction()
}
}
obj.getValue()
9、构造函数里面的this,指向实例化对象
function Person(name) {
this.name = name // 指向实例化对象
console.log(this) // 指向实例化对象
}
let p = new Person() // Person{}
10、构造函数,静态成员中的 this
指向它的构造函数。静态属性和静态方法都是定义在构造函数或类本身上的,不是定义在类的实例上。因此,当你在静态方法中使用 this
关键字时,它指的是定义该静态方法的构造函数或类
function Person(name, age) {
// 省略实例成员
}
// 静态属性
Person.eyes = 2
// 静态方法
Person.walk = function () {
console.log('^_^人都会走路...')
console.log(this.eyes) // 2
console.log(this) // 这里的this指向调用该方法的构造函数,因为Person既是构造函数,也是一个对象
}
Person.walk() // Person{} (this指向调用者Person)
11、构造函数内的方法的this(实例方法的this)指向实例化对象
function Person(name, age) {
// 实例属性
this.name = name;
this.age = age;
// 实例方法
this.greet = function () {
console.log(`Hello, my name is ${this.name},my age is ${this.age}`);
}
}
let person = new Person('小十七',23)
person.greet() // Hello, my name is 小十七,my age is 23
12、构造函数的原型对象(prototype)内的this指向构造函数的实例化对象
function Fn(a, b) {
this.a = a
this.b = b
}
Fn.prototype.THIS = function () {
console.log(this)
}
let fn = new Fn(1, 2)
fn.THIS() // Fn {a: 1, b: 2} ,打印出构造函数的实例化对象
console.log(fn) // Fn {a: 1, b: 2}
改变this指向
call()
方法
- 返回值:使用指定的
this
值和参数调用函数后的结果 - 第一个参数接收一个对象,用于改变this的指向,从第二个参数开始往后都是传递给函数的实参
- 改变this指向后会立即调用被改变this指向的函数
语法:
fn.call( thisArg , a , b , c...)
let obj = {
name: 'Alice'
}
function greet() {
console.log('Hello, ' + this.name)
}
greet.call(obj) // 输出: "Hello, Alice"
apply()
方法
apply()
是一个函数的方法,接收一个对象用于改变this的指向,和一个数组(或类数组对象)解析为参数传给函数- 返回值:使用指定的
this
值和参数调用函数的结果 - 改变this时会立即调用
语法:
fn.apply(thisArg, [Array])
这里有两个参数:
thisArg
:在fn
函数运行时使用的this
值。如果thisArg
是null或undefined,那么this
会被全局对象替代。如果不是对象,那么会被转化成对象。argsArray
:一个数组或者类数组对象,其中的数组元素将作为单独的参数传给func
函数。
这是一个使用apply()
的例子:
function fn(a, b) {
return a + b
}
console.log(fn.apply(null, [1, 2])) // 输出3
在这个例子中,apply()
调用func
函数,并把数组[1, 2]
的元素作为参数。因为this
没有被特别指定,所以它默认为全局对象(在浏览器中通常是window
)。结果为3,因为1加2等于3
bind()
方法
- 返回值:返回一个新函数(改变this指向之后的函数),不会立即调用
bind()
是一个方法,用于改变this的指向,第一个参数是this指向,从第二个参数开始是传给函数的实参- 使用场景:想改变this指向,又不想调用函数时
语法:
fn.bind(thisArg , a , b , c...)
其中:
thisArg
:当fn
执行时this
的值。如果thisArg
是null
或undefined
,那么this
会被全局对象(window)替代。否则,this
就是thisArg
arg1, arg2, ...
:当调用绑定的函数时,作为前缀传递给目标函数的参数
这是一个简单的例子来演示如何使用bind()
:
let obj = {
x: 10,
getX: function() {
return this.x
}
}
let retrieveX = obj.getX
console.log(retrieveX())
// 如果直接这样调用,结果是"undefined",因为此时的this指向全局对象(浏览器环境下的window对象)
let boundGetX = retrieveX.bind(obj)
console.log(boundGetX()) // 10 (通过bind方法,我们把this绑定到了obj对象上)
第二个例子:
<button>按钮</button>
<script>
let btn = document.querySelector('button')
btn.addEventListener('click', function () {
setTimeout(function () {
btn.disabled=true // 直接使用btn变量
}, 2000)
})
</script>
<button>按钮</button>
<script>
let btn = document.querySelector('button')
btn.addEventListener('click', function () {
let that = this //将外部的this赋值给that,外部的this指向btn
setTimeout(function () {
that.disabled = true //通过that就可以获取外部this
}, 2000)
})
</script>
<button>按钮</button>
<script>
let btn = document.querySelector('button')
btn.addEventListener('click', function () {
setTimeout(function () {
this.disabled=true
}.bind(this), 2000) // 使用bind()方法改变y
})
</script>