了解 JavaScript 中的范围函数
Understanding a range function in JavaScript
所以,我是编程新手,在这里遇到了一些麻烦。看,我想写一个小范围的函数,比如 range(a,b)
,它会 return 一个包含 a 和 b 之间所有数字的数组。所以我用谷歌搜索并找到了这个:
const range = (min, max) => [...Array(max - min + 1).keys()].map(i => i + min);
这工作得很好,但我在理解它时遇到了一些麻烦,尤其是 .keys()
部分。我以为 .keys()
是一个对象函数,它将 return 对象的 key/value 对的键,但在我看来,它已被用在数组中。
我哪里理解错了?
感谢您的帮助!
数组有 keys
as well and returns an iterator for returning keys. This requires a spreading into an array or use a function which takes iterables 和 returns 个数组。
为此目的制作了 Array.from
- 这也具有映射功能。
您可以直接将 Array.from
与具有 length
属性 和映射函数的对象一起使用,而不是构建多个数组。
const range = (min, max) => Array.from(
{ length: max - min + 1 },
(_, i) => i + min
);
console.log(...range(7, 9));
数组也有一个 keys
方法,它是这个 range
函数正常工作的核心。
工作原理如下:
- 它创建一个适当长度 (
Array(max - min + 1)
) 的空 (sparse) 数组。
- 它为该数组的有效索引 (
.keys()
) 获取 iterator。数组中的有效索引是数组长度减一的数字 0
。 (从技术上讲,在规范术语中,数组的索引是字符串 属性 名称,如 "0"
、"1"
等,但是 keys
迭代器 return 的数字因为我们通常使用数字来索引数组,这是提供更有用的价值。)
- 它spreads 将迭代器中的元素输出到数组 (
[...]
) 中。
- 它通过映射来自 #3 的数组中的每个值创建一个新数组,并向它们添加
min
值 (.map(i => i + min)
)。
请注意,这会创建多个中间数组和其他对象。这不太重要,但可以更有效地完成。例如,将 Array.from
作为 ,甚至只是一个简单的循环:
const range = (min, max) => {
const result = [];
for (let n = min; n < max; ++n) {
result.push(n); // Or: `result[result.length] = n;` if you want to
// avoid the function call
}
return result;
};
const range = (min, max) => {
const result = [];
for (let n = min; n < max; ++n) {
result.push(n);
}
return result;
};
console.log(range(5, 10));
不过,这看起来并不那么酷。 :-D
但是,我可能根本不会有 range
return 数组,除非我确定那是最终产品我总是需要。相反,我会让它 return 一个迭代器:
const range = function*(min, max) {
for (let n = min; n < max; ++n) {
yield n;
}
};
for (const value of range(0, 10)) {
console.log(value);
}
.as-console-wrapper {
max-height: 100% !important;
}
如果你需要一个数组,你总是可以把它分散到一个数组中(或与 Array.from
一起使用)。
所以,我是编程新手,在这里遇到了一些麻烦。看,我想写一个小范围的函数,比如 range(a,b)
,它会 return 一个包含 a 和 b 之间所有数字的数组。所以我用谷歌搜索并找到了这个:
const range = (min, max) => [...Array(max - min + 1).keys()].map(i => i + min);
这工作得很好,但我在理解它时遇到了一些麻烦,尤其是 .keys()
部分。我以为 .keys()
是一个对象函数,它将 return 对象的 key/value 对的键,但在我看来,它已被用在数组中。
我哪里理解错了?
感谢您的帮助!
数组有 keys
as well and returns an iterator for returning keys. This requires a spreading into an array or use a function which takes iterables 和 returns 个数组。
为此目的制作了 Array.from
- 这也具有映射功能。
您可以直接将 Array.from
与具有 length
属性 和映射函数的对象一起使用,而不是构建多个数组。
const range = (min, max) => Array.from(
{ length: max - min + 1 },
(_, i) => i + min
);
console.log(...range(7, 9));
数组也有一个 keys
方法,它是这个 range
函数正常工作的核心。
工作原理如下:
- 它创建一个适当长度 (
Array(max - min + 1)
) 的空 (sparse) 数组。 - 它为该数组的有效索引 (
.keys()
) 获取 iterator。数组中的有效索引是数组长度减一的数字0
。 (从技术上讲,在规范术语中,数组的索引是字符串 属性 名称,如"0"
、"1"
等,但是keys
迭代器 return 的数字因为我们通常使用数字来索引数组,这是提供更有用的价值。) - 它spreads 将迭代器中的元素输出到数组 (
[...]
) 中。 - 它通过映射来自 #3 的数组中的每个值创建一个新数组,并向它们添加
min
值 (.map(i => i + min)
)。
请注意,这会创建多个中间数组和其他对象。这不太重要,但可以更有效地完成。例如,将 Array.from
作为
const range = (min, max) => {
const result = [];
for (let n = min; n < max; ++n) {
result.push(n); // Or: `result[result.length] = n;` if you want to
// avoid the function call
}
return result;
};
const range = (min, max) => {
const result = [];
for (let n = min; n < max; ++n) {
result.push(n);
}
return result;
};
console.log(range(5, 10));
不过,这看起来并不那么酷。 :-D
但是,我可能根本不会有 range
return 数组,除非我确定那是最终产品我总是需要。相反,我会让它 return 一个迭代器:
const range = function*(min, max) {
for (let n = min; n < max; ++n) {
yield n;
}
};
for (const value of range(0, 10)) {
console.log(value);
}
.as-console-wrapper {
max-height: 100% !important;
}
如果你需要一个数组,你总是可以把它分散到一个数组中(或与 Array.from
一起使用)。