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


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

相关推荐
知识分享小能手1 小时前
React学习教程,从入门到精通, React 属性(Props)语法知识点与案例详解(14)
前端·javascript·vue.js·学习·react.js·vue·react
luckys.one1 小时前
第9篇:Freqtrade量化交易之config.json 基础入门与初始化
javascript·数据库·python·mysql·算法·json·区块链
魔云连洲1 小时前
深入解析:Vue与React的异步批处理更新机制
前端·vue.js·react.js
mCell2 小时前
JavaScript 的多线程能力:Worker
前端·javascript·浏览器
weixin_437830943 小时前
使用冰狐智能辅助实现图形列表自动点击:OCR与HID技术详解
开发语言·javascript·ocr
超级无敌攻城狮3 小时前
3 分钟学会!波浪文字动画超详细教程,从 0 到 1 实现「思考中 / 加载中」高级效果
前端
excel4 小时前
用 TensorFlow.js Node 实现猫图像识别(教学版逐步分解)
前端
gnip4 小时前
JavaScript事件流
前端·javascript
小菜全5 小时前
基于若依框架Vue+TS导出PDF文件的方法
javascript·vue.js·前端框架·json
赵得C5 小时前
【前端技巧】Element Table 列标题如何优雅添加 Tooltip 提示?
前端·elementui·vue·table组件