每日知识点:this 指向之谜——是谁在 call 我?

张开发
2026/4/10 18:24:02 15 分钟阅读

分享文章

每日知识点:this 指向之谜——是谁在 call 我?
引言“这个 this 怎么又 undefined 了”“为什么在对象方法里 this 指向对象回调里就指向 window”“箭头函数里的 this 怎么跟我预想的不一样它是不是有自己的想法”如果你被 this 折磨过你不是一个人。我曾经在一个 Vue 组件里写了一个setTimeout里面用了this.message结果打印出来是undefined。我对着屏幕怒吼“这不科学我明明就在组件实例内部”后来我才明白this 不是看你在哪里定义的而是看你怎么调用的。它就像一个社交达人谁叫它它就跟谁走。今天我们就来扒一扒 this 的“社交规则”。一、this 的四大绑定规则法官宣判版1.1 默认绑定单身狗模式当你直接调用一个普通函数且不在严格模式下this 指向全局对象浏览器里是windowNode 里是global。严格模式下是undefined。functionshowThis(){console.log(this);}showThis();// window非严格模式这叫“默认绑定”——函数被独立调用没有主人this 就只好认全局做爹。1.2 隐式绑定有对象罩着当函数作为对象的方法被调用时this 指向那个对象。constobj{name:张三,greet(){console.log(this.name);}};obj.greet();// 张三 —— this 指向 obj但如果把这个方法拿出来单独调用就回到默认绑定constfnobj.greet;fn();// undefined或 window.name如果存在这就是传说中的“丢失 this”——你把方法从对象身上扒下来它就失去了归属感。1.3 显式绑定硬塞给你用call、apply、bind可以强行指定 this。functiongreet(){console.log(this.name);}constuser{name:李四};greet.call(user);// 李四bind会返回一个新函数永久绑定 this再也改不了除非你用 new 去怼。1.4 new 绑定造物主模式当函数被new调用时this 指向新创建的那个对象。functionPerson(name){this.namename;}constpnewPerson(王五);console.log(p.name);// 王五这四条规则优先级new 绑定 显式绑定 隐式绑定 默认绑定。二、箭头函数this 的“叛逆少年”箭头函数不绑定自己的 this它会捕获定义时所在的 this并且永远不变。constobj{name:赵六,greet:(){console.log(this.name);}};obj.greet();// undefined因为箭头函数的 this 是定义时的外层 this此处外层是 window箭头函数最适合用在回调里比如setTimeout、事件监听能保留外层 this。constobj{name:孙七,greet(){setTimeout((){console.log(this.name);// 孙七 —— 箭头函数保住了 this},100);}};三、经典坑位大赏坑1回调函数里的 thisconstobj{name:周一,greet(){setTimeout(function(){console.log(this.name);// undefined 或 window.name},100);}};解决方案用箭头函数或者在外面缓存const self this。坑2事件监听里的 thisbutton.addEventListener(click,function(){console.log(this);// 指向 button 元素});如果用箭头函数this 就变成外层通常是 window可能不是你想要的。坑3类方法作为回调classMyClass{constructor(){this.name实例;}handle(){console.log(this.name);}}constinstnewMyClass();setTimeout(inst.handle,100);// undefined —— 方法被单独传递丢失 this修复setTimeout(() inst.handle(), 100)或setTimeout(inst.handle.bind(inst), 100)。四、一句话记住 thisthis 指向调用它的那个对象箭头函数除外它指向定义时的爹。更精确版谁调用我我就指向谁没人调用我就指向全局严格模式 undefined箭头函数不跟别人走我出生时的环境就是我的家。五、实战写出一个安全的 this 代码classSearchBox{constructor(inputEl){this.inputElinputEl;this.inputEl.addEventListener(input,this.handleInput.bind(this));// 或者用箭头函数this.handleInput (e) { ... }}handleInput(e){console.log(this);// 指向 SearchBox 实例而不是 input 元素this.search(e.target.value);}search(keyword){console.log(搜索:${keyword});}}六、总结别再被 this 坑了this 是 JavaScript 中最容易出错的概念之一但掌握了绑定规则它就是个纸老虎。记住四个绑定默认、隐式、显式、new加上箭头函数的特例你就能在面试和工作中游刃有余。下次当你看到this变成undefined时先问自己三个问题这个函数是怎么被调用的默认/隐式/显式/new是不是箭头函数是不是在严格模式下答完这三个问题凶手就找到了。每日一问你曾经遇到过最诡异的 this 指向 bug 是什么是在 React 组件里还是在 Vue 的 methods 里评论区分享你的“this 历险记”

更多文章