如何理解JavaScript中的this关键字_JavaScript中this的指向如何确定

发布时间 - 2026-01-06 00:00:00    点击率:
JavaScript 中的 this 指向函数被调用时的执行上下文对象,而非定义时所在对象;普通调用时非严格模式下为全局对象(浏览器中为 window),严格模式下为 undefined;对象方法调用时 this 指向该对象;箭头函数无自有 this,继承外层非箭头函数的 this;new、call、apply、bind 可显式控制 this。

JavaScript 中的 this 不是指“函数定义时所在的对象”,而是“函数被调用时的执行上下文对象”——这个判断必须在每次调用时动态计算,不能靠代码位置猜。

普通函数调用时的 this 指向全局或 undefined

在非严格模式下,直接调用函数(如 foo()),this 指向全局对象(浏览器中是 window);严格模式下是 undefined。这是最容易误判的场景。

常见错误现象:this 在回调里突然变成 windowundefined,尤其在事件监听、定时器、数组方法(如 mapforEach)中传入普通函数时。

  • 避免方式:用箭头函数(不绑定自己的 this)、显式绑定(bind/call/apply)、或改用对象方法调用形式
  • 注意 Node.js 环境中全局对象是 global,不是 window
  • ES Module 脚本默认启用严格模式,所以顶层普通函数调用的 thisundefined

对象方法调用决定 this 绑定到该对象

当函数作为对象属性被调用(如 obj.method()),this 指向 obj。但只看调用形式,不看函数如何定义或赋值。

const obj = {
  name: 'Alice',
  say() {
    console.log(this.name); // 'Alice'
  }
};
const fn = obj.say;
fn(); // this 是 undefined(严格模式),不是 obj!
obj.say(); // this 是 obj

关键点:

  • this 只由「谁点出来的」决定,不是「谁定义的」
  • 一旦把方法赋给变量(fn = obj.say),就丢失了调用主体,变成普通调用
  • 解构赋值也会触发相同问题:const { say } = obj; say(); 同样丢失 this

箭头函数没有自己的 this,继承外层作用域

箭头函数不创建自己的 this,它会沿作用域链向上查找最近的非箭头函数的 this 值。因此它无法通过 callapplybind 改变 this

const obj = {
  name: 'Bob',
  regular() {
    console.log(this.name); // 'Bob'
    const arrow = () => console.log(this.name); // 'Bob'
    arrow();
  }
};
obj.regular();

适用场景:

  • 避免在 setTimeoutPromise.thenaddEventListener 回调中手动 bind(this)
  • 类中定义事件处理器时(class X { handleClick = () => { ... } }
  • 但不要在需要动态 this 的地方用箭头函数,比如想让方法能被不同对象复用时

new 调用和 call/apply/bind 显式控制 this

new Fn() 会让 this 指向新创建的实例;Fn.call(obj, ...)Fn.apply(obj, [...])Fn.bind(obj) 则强制指定 this 值。

容易踩的坑:

  • bind 返回的是新函数,必须调用才生效:obj.method.bind(other)(),漏掉末尾 () 就没执行
  • callapply 立即执行,区别只在参数传法:call 用逗号分隔,apply 用数组
  • 箭头函数无法被 call/apply/bind 修改 this,传进去的值会被忽略

真正难的不是记住规则,而是意识到 this 的值永远取决于「函数怎么被调用」,而不是「函数怎么被写」。哪怕同一个函数,在不同调用形式下 this 可能完全不同。调试时别盯着函数体,先看调用表达式左侧是什么。


# javascript  # java  # js  # node.js  # node  # 处理器  # 浏览器  # app  # win  # 区别  # 作用域 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel模型关联查询教程_Laravel Eloquent一对多关联写法  进行网站优化必须要坚持的四大原则  韩国服务器如何优化跨境访问实现高效连接?  laravel怎么为API路由添加签名中间件保护_laravel API路由签名中间件保护方法  Android仿QQ列表左滑删除操作  如何在云指建站中生成FTP站点?  香港服务器WordPress建站指南:SEO优化与高效部署策略  如何快速打造个性化非模板自助建站?  Laravel Artisan命令怎么自定义_创建自己的Laravel命令行工具完全指南  Laravel观察者模式如何使用_Laravel Model Observer配置  浅谈Javascript中的Label语句  电视网站制作tvbox接口,云海电视怎样自定义添加电视源?  如何在宝塔面板中修改默认建站目录?  零基础网站服务器架设实战:轻量应用与域名解析配置指南  jquery插件bootstrapValidator表单验证详解  教学论文网站制作软件有哪些,写论文用什么软件 ?  Laravel如何使用Blade组件和插槽?(Component代码示例)  如何在HTML表单中获取用户输入并结合JavaScript动态控制复利计算循环  手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?  Laravel如何实现用户注册和登录?(Auth脚手架指南)  网站建设要注意的标准 促进网站用户好感度!  PHP 500报错的快速解决方法  Laravel如何创建自定义Facades?(详细步骤)  安克发布新款氮化镓充电宝:体积缩小 30%,支持 200W 输出  C语言设计一个闪闪的圣诞树  js代码实现下拉菜单【推荐】  EditPlus中的正则表达式 实战(2)  Win11怎么设置虚拟桌面 Win11新建多桌面切换操作【技巧】  香港服务器租用每月最低只需15元?  php打包exe后无法访问网络共享_共享权限设置方法【教程】  如何快速生成专业多端适配建站电话?  js实现点击每个li节点,都弹出其文本值及修改  利用python获取某年中每个月的第一天和最后一天  Laravel如何生成和使用数据填充?(Seeder和Factory示例)  linux top下的 minerd 木马清除方法  Laravel如何集成微信支付SDK_Laravel使用yansongda-pay实现扫码支付【实战】  如何快速搭建高效WAP手机网站吸引移动用户?  如何快速查询域名建站关键信息?  Laravel怎么生成URL_Laravel路由命名与URL生成函数详解  如何将凡科建站内容保存为本地文件?  深圳网站制作平台,深圳市做网站好的公司有哪些?  Laravel全局作用域是什么_Laravel Eloquent Global Scopes应用指南  Laravel如何创建和注册中间件_Laravel中间件编写与应用流程  Laravel Sail是什么_基于Docker的Laravel本地开发环境Sail入门  开心动漫网站制作软件下载,十分开心动画为何停播?  Windows10如何更改计算机工作组_Win10系统属性修改Workgroup  通义万相免费版怎么用_通义万相免费版使用方法详细指南【教程】  怎么用AI帮你为初创公司进行市场定位分析?  公司网站制作需要多少钱,找人做公司网站需要多少钱?  夸克浏览器网页跳转延迟怎么办 夸克浏览器跳转优化