前言
在 JavaScript 中,this 的指向不是在编写时确定的,而是在执行时确定的。理解 this 的关键在于:谁调用了它,它就指向谁(除了箭头函数) 。
一、 this 的四大绑定规则
1. 默认绑定(全局环境)
在全局作用域或普通函数调用中,this 指向全局对象。
- 浏览器环境:指向
window。 - 严格模式 (
'use strict') :指向undefined。
2. 隐式绑定(对象方法)
当函数作为对象的方法被调用时,this 指向该对象。
const obj = {
a: 1,
func() { console.log(this.a); }
};
obj.func(); // 1(this 指向 obj)
⚠️ 隐式丢失:将方法赋值给变量后再调用,this 会指向全局。
const func1 = obj.func;
func1(); // undefined(此时为独立调用,this 指向 window)
3. 显式绑定(call/apply/bind)
通过 call、apply、bind 强行改变 this 的指向。
4. new 绑定(构造函数)
使用 new 关键字调用函数时,this 指向新创建的那个实例对象。
二、 箭头函数:异类的 this
箭头函数没有自己的 this! 它的 this 继承自外层(父级)执行上下文。
- 定义时绑定:它在定义时就已经确定了指向,且后续无法通过
call/bind改变。 - 不指向调用者:它不看谁调用,只看它诞生在哪里。
JavaScript
function func(){
const func2 = () => {
console.log(this); // 这里的 this 继承自 func 的执行上下文
}
func2();
}
func(); // window
三、 原型链与 HTML 事件中的 this
1. 原型链方法
在原型链上添加方法时,this 指向当前调用该方法的实例对象。
Function.prototype.myBind = function(thisArg) {
console.log(this); // 这里的 this 指向调用 myBind 的那个函数对象
};
2. HTML 事件处理
在 HTML 元素的事件属性中,this 指向当前的 HTML 元素本身。
<div onclick="console.log(this)">点击我</div>
//this指向Html元素
四、 面试模拟题(挑战一下)
Q1:嵌套函数中的 this 是如何表现的?如何解决指向丢失?
参考回答: 嵌套函数(非箭头函数)独立调用时,this 指向全局。解决办法有:
- 使用箭头函数(最推荐)。
- 在外层函数定义
let self = this;,在内层通过self访问。 - 使用
bind强行锁定。
Q2:箭头函数可以作为构造函数吗?为什么?
参考回答: 不可以。因为:
- 箭头函数没有自己的
this,无法指向新创建的实例。 - 箭头函数没有
prototype属性。 - 箭头函数没有
arguments对象。
Q3:说出以下代码的执行结果:
var name = "window";
const person = {
name: "obj",
sayName: () => {
console.log(this.name);
}
};
person.sayName();
参考回答: 结果是 "window"
解析:person 是一个对象字面量,它没有自己的块级作用域。箭头函数 sayName 在定义时,其父级上下文是全局执行上下文(window),因此 this 指向 window。