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 才会越来越稳。


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

相关推荐
牧濑红莉23 分钟前
网络安全竞赛pwn全解及第一道ai的wp
javascript·.net
神明不懂浪漫33 分钟前
【第四章】CSS(二)——文本外观属性与复合选择器
前端·css·经验分享·笔记
kyriewen44 分钟前
别再用AI debug了——这5种bug越修越烂
前端·javascript·ai编程
星释2 小时前
鸿蒙智能体开发实战:39.鸿蒙壁纸大师 - 前端卡片显示与交互优化
前端·华为·交互·harmonyos·鸿蒙·火山引擎
顾昂_2 小时前
内存泄漏排查和 Chrome DevTools 使用教程
前端·javascript·面试
IT_陈寒3 小时前
Java线程池这个坑我算是踩明白了
前端·人工智能·后端
An_s3 小时前
rust开发wasm与浏览器(js)交互
javascript·rust·wasm
山河木马4 小时前
GPU自动处理专题4-填充覆盖区域(光栅化)
javascript·webgl·计算机图形学
悦儿遥遥雨14 小时前
PXE + Kickstart 无人值守批量部署系统
linux·javascript·nginx
31535669134 小时前
Superpowers:GPT-5.6 时代下的流程毒瘤
前端·后端