LeetCode / JavaScript No.09 返回传递的参数长度
🗿🗿🗿本系列文档在 LeetCode 30 天 JavaScript 挑战 完成后可看到题解,本人只转载方便自看
问题描述
编写一个函数 argumentsLength ,返回传递给该函数的参数数量。
var argumentsLength = function(...args) {
...
};
argumentsLength(1, 2, 3); // 3
需要计算传递给函数 argumentsLength 的参数数量。这里的参数以剩余参数的形式传递。
剩余参数
在 JavaScript
中,剩余参数是一种允许函数接受不定数量参数的功能。它由三个点 (...
) 后跟一个参数名表示。剩余参数将传递给函数的所有剩余参数收集到一个数组中,即使参数数量事先未知。如果没有传递额外参数,剩余参数也将是一个空数组。
⚠️注意:剩余参数于 arguments
对象是不同的,下面会提到。
语法
function functionName(...args) {
// 函数体
}
上面示例中的剩余参数(在上面的示例中为 args
)可以使用任何有效的标识符名称,但习惯上将其命名为 args
或 rest
以表示其用途。剩余参数应放在函数参数列表的最后。可以在剩余参数之前有其他参数,但剩余参数必须是最后一个。
访问参数
在函数内部,可以将剩余参数(args
)视为普通数组。可以使用数组索引或数组方法如 forEach()
、map()
、filter()
等访问数组的元素。
示例
function sum(...args) {
let total = 0;
for (let number of args) {
total += number;
}
return total;
}
console.log(sum(1, 2, 3, 4)); // 输出: 10
console.log(sum(5, 10, 15)); // 输出: 30
console.log(sum()); // 输出: 0(未传递参数)
sum()
函数使用剩余参数 args
来收集传递给它的所有参数。然后,它遍历 args
数组并计算所有元素的总和。
剩余参数提供了灵活性,消除了在函数声明中明确定义固定数量参数的需要,使代码更简洁且适应性更强。需要注意的是,剩余参数仅收集传递给函数的附加参数,不包括通过命名参数或默认参数值传递的参数。
展开运算符 / 剩余参数
剩余参数后与展开运算符相似,但实际上它们不同。展开运算符和剩余参数之所以看起来相似,是因为它们在 JavaScript
中使用相同的语法 (...
),但它们具有不同的目的并在不同的上下文中使用。
区别
展开运算符用于将数组或可迭代对象(如字符串或集合)中的元素解开为单独的元素。它将元素展开。它通常在需要组合或克隆数组、将数组的单个元素作为参数传递给函数或将可迭代对象转换为数组的情况下使用。
而剩余参数在你想要编写可以接受可变数量参数的函数时非常有用,即它允许你处理动态数量的函数参数,而无需明确定义单独的参数。
简单来说,展开运算符 和 剩余参数刚好相反,展开运算符是展开一个 ‘数组’,剩余参数是收纳所有参数成为一个 ‘数组’。
扩展语法示例:
const array = [1, 2, 3];
console.log([...array]); // 输出: [1, 2, 3]
const string = "hello";
console.log([...string]); // 输出: ['h', 'e', 'l', 'l', 'o']
const set = new Set([1, 2, 3]);
console.log([...set]); // 输出: [1, 2, 3]
解决方法
方法 1: 使用 arguments
参数对象
arguments
对象是 JavaScript
函数内部的一个局部变量,它包含了函数调用时传递给函数的参数列表。arguments
对象是一个类数组对象,它具有类似数组的特性,可以通过索引访问参数,并且有一个 length
属性表示参数的数量。
arguments
对象可以在函数内部使用,用来获取所有传递给函数的参数,即使函数没有明确定义参数名。这对于处理可变数量的参数或者不确定数量的参数非常有用。
需要注意的是,arguments
对象虽然是类数组对象,但它是一个伪数组而不是一个真正的数组,因此它不具备数组的方法,比如 forEach()
、map()
、filter()
等。如果要在 arguments
对象上使用这些方法,需要将其转换为真正的数组。另外,使用 arguments
对象也可能会导致一些性能问题,因为在某些 JavaScript
引擎中,arguments
对象是在函数调用时动态生成的。
在现代 JavaScript
中,通常推荐使用剩余参数(Rest Parameters)语法来替代 arguments
对象,因为剩余参数语法更加简洁和直观,而且是一个真正的数组,可以直接使用数组的方法。
问题实现代码:
var argumentsLength = function(...args) {
return arguments.length;
};
方法 2: 使用剩余参数
var argumentsLength = function(...args) {
return args.length
};
方法的区别
上述两个方法之间的主要区别在于它们访问参数长度的方式:
- 第一个代码片段(
arguments.length
)直接访问特殊的参数对象上的长度属性,而不是明确的将其转换为数组。 - 第二个代码片段(
args.length
)直接访问由剩余参数创建的数组上的长度属性。
伪数组(Array-like objects
)和真数组(Array
)
重要区别
- 类型: 伪数组不是
Array
类的实例。它是一个类似数组的对象,这意味着它具有一些类似数组的特征,但缺少许多数组可用的内置方法和属性。 - 数组方法:
JavaScript
中的数组有许多内置方法,如forEach()
、map()
、push()
、pop()
等。然而,伪数组没有这些数组方法可用。它不会从Array.prototype
继承数组方法。 - 长度: 数组和伪数组都有一个表示元素数量的长度属性。然而,伪数组的长度属性会自动更新以反映传递给函数的参数数量,而数组中的长度属性表示数组中的元素数量。
- 可修改性: 可以使用
push()
、pop()
、splice()
等方法修改数组。相反,在非严格模式下可以修改伪数组的条目,但不能更改其长度,也不能在其上使用像push()
、pop()
和splice()
这样的数组方法。此外,在严格模式下,伪数组实际上是只读的。 - 迭代: 数组和伪数组都可以使用循环或
for...of
等迭代方法进行迭代。但是,当涉及到数组特定的迭代方法(如forEach()
或map()
)时,它们只能直接与数组一起使用。
数组中常用的属性和方法
length: 返回数组中的元素数量。
constructor: 指定创建数组原型的函数。
prototype: 允许向数组的原型对象添加属性和方法。
Symbol.iterator: 返回用于迭代数组元素的迭代器对象。
concat(): 连接两个或多个数组并返回一个新数组。
join(): 将数组的所有元素连接成一个字符串。
push(): 将一个或多个元素添加到数组的末尾并返回数组的新长度。
pop(): 从数组中移除最后一个元素并返回该元素。
shift(): 从数组中移除第一个元素并返回该元素。
unshift(): 将一个或多个元素添加到数组的开头并返回数组的新长度。
slice(): 返回一个从开始到结束(不包括结束)选定的部分的浅拷贝。
splice(): 在指定的索引位置更改数组的内容,删除、替换或添加元素。
indexOf(): 返回元素在数组中第一次出现的索引,如果不存在则返回-1。
lastIndexOf(): 返回元素在数组中最后一次出现的索引,如果不存在则返回-1。
forEach(): 为数组中的每个元素执行提供的函数一次。
map(): 创建一个新数组,其中包含对数组中的每个元素调用提供的函数的结果。
filter(): 创建一个新数组,其中包含通过提供的函数实现的测试的所有元素。
reduce(): 将一个函数应用于累加器和数组中的每个元素,将其减少为单个值。
reduceRight(): 从右到左应用一个函数于累加器和数组的每个元素,将其减少为单个值。
sort(): 原地对数组的元素进行排序并返回排序后的数组。
reverse(): 原地反转数组中元素的顺序。
toString(): 返回表示指定数组及其元素的字符串。
toLocaleString(): 返回表示数组元素的本地化字符串。
includes(): 确定数组是否包含某个值。
some(): 检查数组中是否至少有一个元素满足提供的条件。
every(): 检查数组中是否所有元素都满足提供的条件。
find(): 返回满足提供的条件的数组中的第一个元素。
findIndex(): 返回满足提供的条件的数组中的第一个元素的索引。
fill(): 从开始索引到结束索引将数组中的所有元素填充为静态值。
copyWithin(): 将数组中的一系列元素复制到数组中的另一个位置。
flat(): 创建一个新数组,其中包含所有子数组元素递归连接到指定深度。
flatMap(): 使用映射函数映射每个元素并将结果展平到新数组中。
from(): 从可迭代对象或类似数组对象创建一个新的浅拷贝数组。
isArray(): 确定传递的值是否为数组。
of(): 创建一个包含可变数量元素的新数组。
keys(): 返回包含数组键的新数组迭代器。
values(): 返回包含数组值的新数组迭代器。
entries(): 返回包含数组键值对的新数组迭代器。
面试题
解释 JavaScript 中的参数对象是什么?
参数对象是 JavaScript
中所有函数内部都可用的特殊对象。它包含一个类似数组的参数集合,允许访问参数,即使它们未被明确定义为函数参数。
可以修改参数对象吗?
可以,通过直接为其元素分配新值来修改参数对象。但重要的是注意,参数对象不是真正的 JavaScript
数组,因此不具有像 push()
、pop()
等数组方法可直接修改它。相反,可以使用索引表示法(arguments[index] = value
)修改元素。
可以使用剩余参数语法来解决这个问题吗?
可以,在 ECMAScript 6(ES6)开始,JavaScript
引入了剩余参数语法,由 ...args
表示,允许将多个函数参数收集到一个数组中。间方法2。
如何将参数对象转换为常规数组?
最常见的方法是使用展开运算符(...
)将参数对象的元素解包到一个新数组中。
function convertToArray(...args) {
return [...args];
}
另一种方法是使用 Array.from()
方法从参数对象创建一个新数组。