JavaScript 严格模式下 arguments 的区别

标签:#前端 #JavaScript #严格模式 #arguments #学习笔记

一、arguments 是什么?

arguments 是函数内部的类数组对象(Array-like),包含了函数调用时传入的所有实参。

javascript 复制代码
function foo() {
  console.log(arguments);       // [1, 2, 3]
  console.log(arguments[0]);    // 1
  console.log(arguments.length); // 3
}
foo(1, 2, 3);

⚠️ 它不是真正的数组 ,没有 push、map、forEach 等方法(除非用 Array.from() 转换)。

二、如何开启严格模式

javascript 复制代码
// 全局严格模式
'use strict';

// 函数级严格模式
function bar() {
  'use strict';
  // 此函数内启用严格模式
}

三、严格模式 vs 非严格模式的核心区别

🔴 区别一:arguments 不可被修改来影响命名参数(最重要)

非严格模式(二者联动)

scss 复制代码
function foo(a, b) {
  console.log(a, b);        // 1, 2
  arguments[0] = 100;
  console.log(a, b);        // 100, 2  ← a 被改变了!
}
foo(1, 2);

非严格模式下,修改 arguments[n] 会同步修改对应的命名参数。

严格模式(二者独立)

javascript 复制代码
'use strict';
function foo(a, b) {
  console.log(a, b);        // 1, 2
  arguments[0] = 100;
  console.log(a, b);        // 1, 2  ← a 没变!
}
foo(1, 2);

严格模式下,arguments 和命名参数完全独立,互不影响。

🔴 区别二:arguments.callee 被禁用

非严格模式(可用)

javascript 复制代码
function factorial(n) {
  if (n <= 1) return 1;
  return n * arguments.callee(n - 1);  // ✅ 正常执行
}
console.log(factorial(5)); // 120

arguments.callee 指向当前正在执行的函数本身,常用于匿名函数递归。

严格模式(报错)

javascript 复制代码
'use strict';
function factorial(n) {
  if (n <= 1) return 1;
  return n * arguments.callee(n - 1);  // ❌ TypeError!
}

严格模式下访问 arguments.callee 会直接抛出 TypeError。

✅ 替代方案

kotlin 复制代码
// 方案1:命名函数直接调用自身
function factorial(n) {
  if (n <= 1) return 1;
  return n * factorial(n - 1);
}

// 方案2:使用箭头函数 + 函数名(尾递归友好)
const factorial = (n) => {
  if (n <= 1) return 1;
  return n * factorial(n - 1);
};

// 方案3:用函数表达式赋给变量
const factorial = function f(n) {
  if (n <= 1) return 1;
  return n * f(n - 1);
};

🔴 区别三:arguments.caller 被禁用

非严格模式

scss 复制代码
function inner() {
  console.log(arguments.caller);  // 返回调用 inner 的外部函数
}
function outer() {
  inner();
}
outer();

严格模式

javascript 复制代码
'use strict';
function inner() {
  console.log(arguments.caller);  // ❌ TypeError!
}

arguments.caller 和 arguments.callee 在严格模式下都被禁止,原因是它们存在安全隐患(可以访问调用栈)。

🟡 区别四:arguments 不会追踪剩余参数(Spread Rest)

严格模式引入了 ...rest 语法,它与 arguments 的行为完全不同:

javascript 复制代码
'use strict';

function foo(a, ...rest) {
  console.log(arguments.length); // 实参个数
  console.log(rest.length);      // 剩余参数个数
}

foo(1, 2, 3, 4);
// arguments.length → 4(所有实参)
// rest.length → 3(去掉 a 之后的部分:[2, 3, 4])

关键区别:

  • arguments:类数组,包含所有实参
  • ...rest:真正的数组 ,只包含未匹配命名参数的部分

四、完整对比表

特性

非严格模式

严格模式

修改 arguments[n] 影响命名参数

✅ 会影响

❌ 不影响

arguments.callee

✅ 可用

❌ TypeError

arguments.caller

✅ 可用

❌ TypeError

arguments 与 rest 参数共存

✅ 可共存

✅ 可共存(但行为独立)

五、为什么严格模式要限制 arguments?

1. 性能优化

非严格模式下,JS 引擎必须维护 arguments 和参数之间的双向绑定关系,这导致无法对函数参数进行某些优化。严格模式下二者独立,引擎可以更高效地处理参数。

2. 安全性

arguments.callee 和 arguments.caller 允许访问调用栈,存在被利用来进行安全攻击的风险。

3. 代码可读性

现代 JS 推荐使用命名函数 或rest 参数 替代 arguments 的各种黑魔法,代码更清晰。

六、现代推荐写法

javascript 复制代码
'use strict';

// ❌ 旧写法:依赖 arguments
function sum() {
  let total = 0;
  for (let i = 0; i < arguments.length; i++) {
    total += arguments[i];
  }
  return total;
}

// ✅ 新写法:使用 rest 参数
function sum(...nums) {
  return nums.reduce((acc, n) => acc + n, 0);
}

// ✅ 新写法:rest + 命名参数结合
function log(prefix, ...messages) {
  messages.forEach(msg => console.log(prefix, msg));
}
log('[INFO]', 'hello', 'world');

总结

严格模式的核心改变 :将 arguments 从一个"神奇的对象"变成了一个普通的类数组,切断了它与命名参数的隐式绑定,并禁用了不安全的 callee/caller 属性。在现代 JS 开发中,推荐使用 ...rest 参数替代 arguments。

相关推荐
何何____11 小时前
Vue 全局事件总线详解
前端·javascript·vue.js
涉密IT资质笔记12 小时前
涉密人员脱密期管理规范:期限分级模型、就业限制边界与违规认定标准
java·服务器·前端·网络·数据库
u01110267512 小时前
工具页案例图如何编写 alt让图片说明与处理场景对应
java·前端·javascript·图像处理·人工智能·算法·ai作画
事圆则缓12 小时前
Flutter 状态管理框架对比(五):GetX 的响应式、依赖注册与生命周期
前端·javascript·flutter
广州智造13 小时前
Radioss复合材料使用的单元属性
前端·设计·cad·建模·cae·radioss
张宏宇13 小时前
我把微软开源的 tgrep 做成了本地版 GitHub Code Search:45,629 个文件里搜一次 10ms
前端·后端
huakoh14 小时前
MCP 调用超时后别急着重试:三步读回分清执行状态
前端
打工仔折腾 AI14 小时前
把模型切换交给平台:用蓝耘智能路由搭建商品评论分析工具
java·服务器·前端·后端·python·性能优化·ai agent 实战
不可能片场14 小时前
Electron 发布标题的冒号 击穿命令行解析
前端·electron
5008414 小时前
React Native for OpenHarmony 实战:三方库 react-native-crypto-js 的鸿蒙化适配指南
javascript·react native·性能优化·electron·harmonyos