this 到底指向谁?严格模式和作用域那些坑全讲明白了

理解运行机制,比掌握语法更重要。

引言

JavaScript 作为前端开发的核心语言,看似简单,实则隐藏着不少运行时的"小机关"。

你可能遇到过这些困惑:

  • varlet 到底差在哪?
  • this 到底指向谁?
  • "use strict" 到底严格在哪?

这篇文章就用 例子 + 原理,带你搞懂 JS 的运行底层逻辑,从变量声明、作用域,到 this 指向和严格模式。


1️⃣ 变量声明:varletconst 真不同

var:老派选手,默认上全局

js 复制代码
var a = 1;
console.log(window.a); // 1

在浏览器环境中,var 声明的变量会挂在 window 对象上,相当于 window.a = 1

这就意味着,所有页面代码都可以访问和修改这个变量,容易产生污染或冲突。

let / const:ES6 新时代的安全声明

js 复制代码
let b = 2;
console.log(window.b); // undefined

使用 letconst 声明的变量,不会挂到全局对象上,而是局部存在于当前块级作用域中。

此外:

  • let 支持重新赋值,const 不支持;
  • 它们都有"暂时性死区"(TDZ):在声明前访问会报错。

2️⃣ 严格模式:让 JS 不再"睁一只眼闭一只眼"

启用方式:

js 复制代码
"use strict";

在严格模式下:

  • 禁止未声明变量直接赋值;
  • 禁止删除变量名;
  • this 在普通函数中不再默认指向 window,而是 undefined
  • 命名函数表达式的名字是只读的;

看看这个例子👇:

js 复制代码
"use strict";
(function b() {
  var b = 20;
  console.log(b); // 20,而不是函数名
})();

你可能听说「函数名在严格模式下是只读的」,于是以为变量无法覆盖。但实际上 var b = 20 是合法的,它创建了一个新的局部变量,屏蔽了函数名变量 b ,所以输出的是 20

真正只读限制的例子如下:

js 复制代码
"use strict";
(function b() {
  b = 123; // ❌ TypeError:不能给函数名 b 重新赋值
})();

3️⃣ this:不是写在哪,而是怎么调用

this 的值,总是函数执行时决定的,而不是写代码的位置。

来看几个经典场景:

✅ 作为对象方法调用:

js 复制代码
var obj = {
  name: '娄老板',
  say() {
    console.log(this.name);
  }
};
obj.say(); // 输出:娄老板

❌ 普通函数调用:

js 复制代码
var fn = obj.say;
fn(); // 非严格模式下输出:window.name(如果有);严格模式下为 undefined

✅ 构造函数中,this 指向实例对象:

js 复制代码
function Person(name) {
  this.name = name;
}
const p = new Person('labula');
console.log(p.name); // labula

⚠️ 如果忘记 new

js 复制代码
const p2 = Person('小明');
console.log(window.name); // 被污染了!this 指向 window

4️⃣ window 与全局变量:曾经的设计,现在的"坑"

早期 JS 设计时,所有全局变量都挂在 window 上,是为了方便浏览器访问。

这也让下面的行为成立:

js 复制代码
var user = '张三';
console.log(window.user); // 张三

但是这会让全局空间变得非常容易污染。

所以 letconst 就成为更好的选择,它们不会绑定到全局对象:

js 复制代码
let score = 99;
console.log(window.score); // undefined

总结回顾

概念 特性/行为
var 声明 会挂到 window,作用域为函数级
let / const 块级作用域,不挂 window,有 TDZ
this 运行时决定,严格模式下默认是 undefined
严格模式 更安全,限制更多,调试更容易

写在最后

JavaScript 是一门看起来随和,实则套路很多的语言。this 指向、作用域规则、严格模式这些东西不难,但很容易忽略。

它们藏在一些看似"正常"的代码背后,很多 bug 其实都是对这些机制理解不到位导致的。

希望这篇文章能帮你把一些模糊地带捋清楚。真正理解它们,写 JS 才会越来越稳。


如果你觉得有帮助,欢迎点赞、收藏或分享这篇文章!

相关推荐
晚烛2 分钟前
CANN + 物理信息神经网络(PINNs):求解偏微分方程的新范式
javascript·人工智能·flutter·html·零售
saber_andlibert28 分钟前
TCMalloc底层实现
java·前端·网络
逍遥德29 分钟前
如何学编程之01.理论篇.如何通过阅读代码来提高自己的编程能力?
前端·后端·程序人生·重构·软件构建·代码规范
冻感糕人~44 分钟前
【珍藏必备】ReAct框架实战指南:从零开始构建AI智能体,让大模型学会思考与行动
java·前端·人工智能·react.js·大模型·就业·大模型学习
程序员agions1 小时前
2026年,“配置工程师“终于死绝了
前端·程序人生
alice--小文子1 小时前
cursor-mcp工具使用
java·服务器·前端
晚霞的不甘1 小时前
揭秘 CANN 内存管理:如何让大模型在小设备上“轻装上阵”?
前端·数据库·经验分享·flutter·3d
小迷糊的学习记录1 小时前
0.1 + 0.2 不等于 0.3
前端·javascript·面试
空&白2 小时前
vue暗黑模式
javascript·vue.js
梦帮科技2 小时前
Node.js配置生成器CLI工具开发实战
前端·人工智能·windows·前端框架·node.js·json