清晰透彻的了解JavaScript的this指向问题
this指向
this是函数体内的一个关键字, 不同函数和不同的环境都会影响this的值
function函数, this默认指向函数调用者
箭头函数, this指向外层作用域this的值
node环境中, 注意全局不再是window, 而是global对象
注意: 严格模式下, this无法指向window, 并且 this变量无法重新赋值
this绑定规则
1. 默认绑定: 看调用者
- 案例1: 按钮事件中this的值
<button onclick="btn2()">再点下</button>
function btn2(){ // 标签上绑定的事件也是在window环境
console.log(this); // 默认由window调用
}
- 案例2: 默认window调用方法
function fnOne(){
console.log(this); // window
}
fnOne(); // 其实是window.fnOne(), 所以调用者是window
- 案例3: 定时器回调函数
setTimeout(function(){ // setTimeout运行在Window的环境下
console.log(this); // 默认指向window
}, 0);
- 案例4: 匿名自调用函数
(function(){ // 匿名自调用函数运行在window环境下
console.log(this); // 代码默认前面都有个window.调用, 所以this默认指向window
})();
2. 隐式绑定: 看调用者
- 案例1: JS获取标签.事件函数
<button id="btn">点我</button>
document.getElementById("btn").onclick = function(){
console.log(this); // onclick事件绑定到按钮, 所以this指向btn按钮
}
- 案例2: 对象调用函数
let obj = {
a: "web前端",
b: function(){
console.log(this); // obj对象
}
}
obj.b(); // b函数的调用者是obj
- 案例3: 取出函数, 再调用
let obj2 = {
a: "web前端",
b: function(){
console.log(this); // window
}
}
let fn = obj2.b; // 这里不是调用函数, 而是取出函数
fn(); // 默认前面有个window在调用.
- 案例4: 返回函数再调用
let obj3 = {
a: "web前端3",
b: function(){
return function(){
console.log(this); // window
}
}
}
let fn2 = obj3.b(); // 调用后里面return出来function(){}赋予给fn2变量
fn2(); // 默认前面有个window
- 案例5: 返回对象, 调用里面函数
let obj4 = {
a: "web前端",
b: function(){
return {
c: "h5啊",
d: function(){
console.log(this); // 指向当前c, d为key的此对象
}
}
}
}
obj4.b().d(); // obj4.b() 得到对象, 然后对象.d()调用的, 所以看好调用者是谁
3. 硬绑定: 直接修改this指向
使用call和apply, 会触发函数, 替换函数内this该指向的值
如果不传或者传null, 还是默认该指向谁就指向谁
function Person(){
this.username = "";
this.age = 0;
}
let obj = {};
Person.call(obj); // call/apply效果相同, 调用Person函数, 修改函数里this指向的值为obj对象, 并且在obj对象上添加username和age属性
// obj的值: {username: "", age: 0}
4. new 绑定
默认配合构造函数使用, 使this指向新的对象
function objectFactory(Base, ...arr) {
// Base 是new 后面的类名
let obj = new Object(); //从Object.prototype上克隆一个对象
obj.__proto__ = Base.prototype; // 继承Base原型里属性/方法
Base.call(obj, ...arr); // 继承Base构造函数里属性/方法
return obj; //返回 obj
}
注意
绑定优先级 new > 硬绑定 > 隐式 > 默认
本文来自博客园,作者:JackieDYH,转载请注明原文链接:https://www.cnblogs.com/JackieDYH/p/17634715.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现