js函数的隐式arguments
1.1 背景
JavaScript 允许函数在调用时传入的实参个数和函数定义时的形参个数不一致, 比如函数在定义时声明了 n 个参数, 在调用函数时不一定非要传入 n 个参数,例如:
1
2
3
4
5
|
// 1. 定义有一个形参的函数fn() function fn(arg){} // 2. 在调用时传入 0 个或 多个参数,并不会报错 fn(); // 传入 0 个参数 fn(1, 'a' ,3); // 传入多个参数 |
1.2 arguments 与 形参的对应关系
arguments是个类数组结构,它存储了函数在调用时传入的所有实参, 通过访问它的length属性可以得到其中保存的实参的个数,并可以通过arguments[n]按顺序取出传入的每个参数(n=1,2,..,arguments.length-1)。
参数在arguments中保存的顺序和传入的顺序相同, 同时也和形参声明的顺序相同,例如:
1
2
3
4
5
6
|
function fn(arg1, arg2, arg3){ console.log(arg1 === arguments[0]); // true console.log(arg2 === arguments[1]); // true console.log(arg3 === arguments[2]); // true } fn(1,2,3); // 调用 |
当传入的实参多于形参个数时,想要获得多余出的实参,就可以用arguments[n]来获取了, 例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// 定义只有一个形参的函数 function fn(arg1){ console.log( 'length of arguments is:' ,arguments.length); console.log( 'arguments[0] is:' , arguments[0]); // 获取传入的第一个实参, 也就是形参 arg1 的值 console.log( 'arguments[1] is:' , arguments[1]); // 获取第二个实参的值, 没有形参与其对应 console.log( 'arguments[2] is:' , arguments[2]); // 获取第二个实参的值, 没有形参与其对应 } fn(1,2,3); // 传入 3 个实参 // 可以得到实际上传入的实参的个数并取出所有实参 // length of arguments is: 3 // arguments[0] is: 1 // arguments[1] is: 2 // arguments[2] is: 3 |
1.3 arguments 与 形参的值相互对应
在非严格模式下, 修改arguments中的元素值会修改对应的形参值;同样的,修改形参的值也会修改对应的arguments中保存的值。下面的实验可以说明:
1
2
3
4
5
6
7
8
9
10
11
|
function fn(arg1, arg2){ // 1. 修改arguments元素,对应的形参也会被修改 arguments[0] = '修改了arguments' ; console.log(arg1); // 2. 修改形参值,对应的arguments也会被修改 arg2 = '修改了形参值' ; console.log(arguments[1]); } fn(1,2); // '修改了arguments' // '修改了形参值' |
但是,在严格模式下不存在这种情况, 严格模式下的arguments和形参的值之间失去了对应的关系:
1
2
3
4
5
6
7
8
9
10
11
12
|
'use strict' ; // 启用严格模式 function fn(arg1, arg2){ // 修改arguments元素,对应的形参也会被修改 arguments[0] = '修改了arguments' ; console.log(arg1); // 修改形参值,对应的arguments也会被修改 arg2 = '修改了形参值' ; console.log(arguments[1]); } fn(1,2); // 1 // 2 |
注意: arguments 的行为和属性虽然很像数组, 但它并不是数组,只是一种类数组结构:
1
2
3
4
5
|
function fn(){ console.log( typeof arguments); // object console.log(arguments instanceof Array); // false } fn(); |
1.4 为什么要了解 arguments
在ES6中, 可以用灵活性更强的解构的方式(...符号)获得函数调用时传入的实参,而且通过这种方式获得的实参是保存在真正的数组中的,例如:
1
2
3
4
5
6
7
|
function fn(...args){ // 通过解构的方式得到实参 console.log(args instanceof Array); // args 是真正的数组 console.log(args); // 而且 args 中也保存了传入的实参 } fn(1,2,3); // true // Array(3) [1, 2, 3] |
那么在有了上面这种更加灵活的方式以后,为什么还要了解arguments呢? 原因是在维护老代码的时候可能不得不用到它。
2. 函数上下文: this
在函数调用时, 函数体内也可以访问到 this 参数, 它代表了和函数调用相关联的对象,被称为函数上下文。
this的指向受到函数调用方式的影响, 而函数的调用方式可以分成以下4种:
- 直接调用, 例如: fn()
- 作为对象的方法被调用, 例如: obj.fn()
- 被当做一个构造函数来使用, 例如: new Fn()
- 通过函数 call() 或者 apply() 调用, 例如: obj.apply(fn) / obj.call(fn)
下面分别讨论以上 4 种调用方式下 this 的指向.
2.1 直接调用一个函数时 this 的指向
有些资料说在直接调用一个函数时, 这个函数的 this 指向 window, 这种说法是片面的, 只有在非严格模式下而且是浏览器环境下才成立, 更准确的说法是:在非严格模式下, this值会指向全局上下文(例如在浏览器中是window, Node.js环境下是global)。而在严格模式下, this 的值是 undefined。实验代码如下:
1
2
3
4
5
|
// 非严格模式 function fn(){ console.log( this ); } fn(); // global || Window |
严格模式下:
1
2
3
4
5
|
'use strict' ; function fn(){ console.log( this ); } fn(); // undefined |
总结: 在直接调用一个函数时, 它的 this 指向分成两种情况: 在非严格模式下指向全局上下文, 在严格模式下指向 undefined.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· .NET Core 中如何实现缓存的预热?
· 三行代码完成国际化适配,妙~啊~
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?