写本《JavaScript简餐》系列文章的目的是记录在阅读学习《JavaScript高级程序设计(第4版)》一书时出现的各个知识点。虽是对读书的笔记和总结,但是希望它轻量、简洁、犀利,不会引起阅读疲劳,可以在碎片化时间和闲暇之余轻巧地沐浴一下知识点。每篇文章只针对一个小部分进行讲解式的梳理,来达到个人复习总结和分享知识的目的。
function add(x, y) { console.log(`一共传进来${arguments.length}个参数哦。`); // 一共传进来2个参数哦。 return arguments[0] + arguments[1]; } console.log(add(2, 3)); // 5这里的arguments[0]和arguments[1]就对应着函数参数中指定的x和y。调用函数时传了2和3两个参数,我们也可以看到arguments.length确实是2。 那这时候我们可能会突然有个大胆的想法,我不在function后面的括号里写形参了可不可以???当然可以!来看一下:
function sub() { return arguments[0] - arguments[1]; } console.log(sub(5, 3)); // 2可见,依然可以拿到参数来进行运算。这就表明,ECMAScript函数的参数只是为了方便才写出来的,并不是必须写出来的。与其他语言不同,在ECMAScript中的形式参数不会创建让之后的调用必须匹配的函数签名。这是因为根本不存在验证形式参数的机制。 arguments对象另一个有意思的地方就是,它的值始终会与对应的形参同步。来看下面的例子:
function add(x, y) { console.log(`y是${y}~`); // y是2~ arguments[1] = 10; console.log(`y现在是${y}!`); // y现在是10! return x + y; } console.log(add(3, 2)); // 13可以看到,调用函数时传的是2和3,但是在函数中给arguments[1]赋值10之后,传给形参y的值也变成10了,而不是原来的2。说明了,arguments对象的值始终会与对应的形参同步。但这并不意味着它们都访问同一个内存地址,他们在内存中还是分开的,只不过会保持同步而已。 另外还要记住一点:如果只传了一个参数,然后把arguments[1]设置成了10,那么这个值不会反应到第二个形参y上。这是因为arguments对象中的值是你调用函数时实际传的那些参数,而不是定义函数时给出的形式参数。看一下演示:
function add(x, y = 1) { console.log(`y是${y}~`); // y是1~ arguments[1] = 10; console.log(`y现在是${y}!`); // y现在是1! return x + y; } console.log(add(3)); // 4结果就是y还是我们定义形参时给的默认值1,给arguments对象赋值后y也没有随之同步。 此外,对于形式参数而言,如果调用函数时没有传这个参数,那么它的值就是undefined。这就类似于定义了变量而没有初始化。比如,如果只给add函数传了一个参数,那么y的值就是undefined:
function add(x, y) { console.log(y); // undefined console.log(arguments[1]); // undefined } add(3);严格模式下,arguments会有一些变化。首先,像前面那样给arguments[1]赋值不会再影响y的值。其次,在函数中尝试重写arguments对象会报错:
<script> "use strict"; // 严格模式 function add(x, y) { console.log(`y是${y}~`); // y是2~ arguments[1] = 10; console.log(`y现在是${y}!`); // y现在是2! return x + y; } console.log(add(3, 2)); // 5 </script> <script> "use strict"; // 严格模式 function add(x, y) { console.log(`y是${y}~`); arguments = {}; // Uncaught SyntaxError: Unexpected eval or arguments in strict mode console.log(`y现在是${y}!`); return x + y; } console.log(add(3, 2)); </script>
function add(x, y) { console.log(arguments); // [1, 2] return x + y; } const sub = (x, y) => { console.log(arguments); // Uncaught ReferenceError: arguments is not defined return x - y; }; add(1, 2); sub(5, 3);虽然箭头函数没有arguments对象,但可以在包装函数中把它提供给箭头函数:
function subFunction(x, y) { const sub = () => { console.log(arguments); // [5, 3] return arguments[0] - arguments[1]; }; return sub(); } console.log(subFunction(5, 3)); // 2 //有点脱裤子放屁的意思呢,哈哈哈。