严格模式(Strict Mode)全面解析

严格模式是 ES5 引入的一种限制性执行模式,通过消除 JavaScript 语言的一些不合理、不严谨之处,减少语法陷阱,提高代码安全性和运行效率;

启用严格模式

  1. 严格模式可作用于全局或函数局部 (推荐局部,避免污染全局)

  2. 注意:‘use strict’ 必须是代码块的第一个语句 (前面不能有除注释外的任何代码),否则失效;

// 1. 全局严格模式(不推荐,会影响所有代码)
'use strict';

// 2. 函数局部严格模式(推荐,仅作用于当前函数)
function fn() {
'use strict';
// 严格模式下的代码
}

// 3. ES6 模块/类默认启用严格模式(无需手动声明)
export const a = 1; // 模块内自动严格模式
class Test {} // 类内自动严格模式

严格模式的核心规则(重点)

常规模式行为 严格模式行为 目的
未声明变量赋值自动创建全局变量 直接抛出 ReferenceError 杜绝意外全局变量
this 在全局函数中指向 window 全局函数中 thisundefined 避免误操作全局对象
函数参数名可重复 (后定义覆盖前) 参数名重复抛出 SyntaxError 避免参数名冲突
delete 不可配置属性不报错 (静默失败) 抛出 TypeError 明确删除操作的合法性
允许八进制字面量 (如 0123) 禁止八进制字面量 (需用 0o123) 统一数值语法
with 语句可用 禁止使用 with 语句 避免作用域混乱,提升性能
变量 / 函数可重写 eval/arguments 禁止重写 eval/arguments 保护核心对象
arguments 与实参联动 (修改实参同步修改 arguments) arguments 是实参的静态副本 避免隐式联动问题
允许 eval 注入变量到当前作用域 eval 有独立作用域 (仅内部可访问) 减少作用域污染
禁止为只读属性赋值 (静默失败) 抛出 TypeError 明确赋值错误
caller/callee 属性可用 访问 arguments.callee/caller 抛出 TypeError 禁止递归依赖,优化性能

关键规则示例

  1. 禁止未声明变量赋值

    // 常规模式:自动创建全局变量
    a = 10; // 全局变量 a = 10
    
    // 严格模式:抛出 ReferenceError
    'use strict';
    b = 20; // Uncaught ReferenceError: b is not defined
    
  2. this 指向变化

    // 常规模式:全局函数 this → window
    function fn1() {
      console.log(this); // window
    }
    fn1();
    
    // 严格模式:全局函数 this → undefined
    'use strict';
    function fn2() {
      console.log(this); // undefined
    }
    fn2();
    
    // 构造函数忘记 new:常规模式 this → window,严格模式抛错
    function Person() {
      'use strict';
      this.name = '张三'; // 未 new 调用时:Uncaught TypeError: Cannot set property 'name' of undefined
    }
    Person(); // 报错(需 new Person())
    
  3. 参数名不可重复

    // 常规模式:参数名重复,后一个覆盖前一个
    function fn(a, a) {
      console.log(a); // 2
    }
    fn(1, 2);
    
    // 严格模式:抛出 SyntaxError
    'use strict';
    function fn(a, a) {} // Uncaught SyntaxError: Duplicate parameter name not allowed in this context
    
  4. arguments 静态化

    // 常规模式:arguments 与实参联动
    function fn(a) {
      a = 2;
      console.log(arguments[0]); // 2
    }
    fn(1);
    
    // 严格模式:arguments 是静态副本,不联动
    'use strict';
    function fn(a) {
      a = 2;
      console.log(arguments[0]); // 1
    }
    fn(1);
    
  5. 禁止删除不可配置属性

    // 常规模式:静默失败
    delete Object.prototype; // false(无报错)
    
    // 严格模式:抛出 TypeError
    'use strict';
    delete Object.prototype; // Uncaught TypeError: Cannot delete property 'prototype' of function Object() { [native code] }
    

经典面试题

以下代码在严格模式下输出什么?为什么?

'use strict';
var obj = {
  name: '李四',
  sayName: function() {
    console.log(this.name);
  }
};
var fn = obj.sayName;
fn();
1. 抛出 Uncaught TypeError: Cannot read property 'name' of undefined
2. 解析:
    严格模式下,全局执行的函数 this 指向 undefined(而非 window);
    fn 是独立调用(而非 obj.sayName()),this 绑定丢失,指向 undefined;
    访问 undefined.name 触发类型错误;

严格模式下,arguments.callee 为什么不能用?如何替代?

// 常规模式:递归可用 arguments.callee
function factorial(n) {
  if (n === 1) return 1;
  return n * arguments.callee(n - 1);
}
console.log(factorial(5)); // 120

// 严格模式:以下代码报错,如何修复?
'use strict';
function factorial(n) {
  if (n === 1) return 1;
  return n * arguments.callee(n - 1);
}
'use strict';
function factorial(n) {
  if (n === 1) return 1;
  return n * factorial(n - 1); // 直接用函数名
}
console.log(factorial(5)); // 120

// 报错原因:严格模式禁止访问 arguments.callee(会抛出 TypeError),目的是避免递归依赖、提升代码可维护性;
// 替代方案:使用函数名递归(或命名函数表达式):

以下代码在严格模式下是否报错?说明原因

'use strict';
eval('var x = 10;');
console.log(x);
1. 答案:抛出 ReferenceError: x is not defined
2. 解析:
    常规模式下,eval 内声明的变量会注入到当前作用域;
    严格模式下,eval 有独立的作用域,内部变量仅在 eval 内有效,外部无法访问;

严格模式下,以下代码执行结果是什么?

'use strict';
function test(a, b) {
  a = 10;
  b = 20;
  console.log(arguments[0], arguments[1]);
}
test(1, 2);
1. 答案:输出 1 2
2. 解析:严格模式下 
    arguments 是实参的静态副本,修改形参不会同步到 arguments;
    常规模式下会输出 10 20;

严格模式下,为什么禁止使用 with 语句?

  1. 答案:

    1. with 语句会创建临时作用域,导致 JS 引擎无法优化代码 (作用域查找变慢),降低性能;
    2. with 容易导致变量名冲突 (如 with(obj) { a = 1; } 无法确定 a 是全局变量还是 obj 的属性)
    3. 严格模式禁用 with,强制开发者使用更清晰的写法 (如 obj.a = 1),提升代码可读性和性能;
  2. with 语句的工作原理 (作用域链扩展)

    1. JS 执行代码时,会通过作用域链查找变量 / 属性:
    2. 正常情况下,作用域链顺序:当前执行上下文的变量对象 外层函数变量对象 全局变量对象;
    3. 进入 with 代码块时,引擎会创建一个临时变量对象 (包含传入对象的所有属性),并将其插入到作用域链的最顶端;
    4. 代码块内查找属性时,优先查这个临时对象,找不到再按原作用域链查找;
    5. 退出 with 代码块后,临时变量对象被移除,作用域链恢复原样;
打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

你好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. 严格模式(Strict Mode)全面解析
    1. 1.1. 启用严格模式
    2. 1.2. 严格模式的核心规则(重点)
    3. 1.3. 关键规则示例
  2. 2. 经典面试题
    1. 2.1. 以下代码在严格模式下输出什么?为什么?
    2. 2.2. 严格模式下,arguments.callee 为什么不能用?如何替代?
    3. 2.3. 以下代码在严格模式下是否报错?说明原因
    4. 2.4. 严格模式下,以下代码执行结果是什么?
    5. 2.5. 严格模式下,为什么禁止使用 with 语句?