1export const useHook = (
2 values: number[]
3) => {
4 const colorScale = useMemo(() => {
5 const min = Math.min(...values);
6 const max = Math.max(...values);
7
8 return ...;
9 }, [values]);
10
11 return ...;
12};
问题描述 Link to heading
1Math.max(...Array(1000000).fill(1))
2
3/**
4VM746:1 Uncaught RangeError: Maximum call stack size exceeded
5 at Math.max (<anonymous>)
6 at <anonymous>:1:6
7*/
在使用超长数组进行 Math.max
运算时,报错 Maximum call stack size exceeded
。
原因分析 Link to heading
原因很简单噻,看一看 Javascript 的 Runtime Environment:
Call Stack,也就是调用栈长度是有限的。你可以调用这段代码看看你的调用栈长度:
1var i = 0;
2function inc() {
3 i++;
4 inc();
5}
6
7try {
8 inc();
9}
10catch(e) {
11 // The StackOverflow sandbox adds one frame that is not being counted by this code
12 // Incrementing once manually
13 i++;
14 console.log('Maximum stack size is', i, 'in your current browser');
15}
16
17// Maximum stack size is 11010 in your current browser
我在 Chrome 中运行结果是 11010,通过二分法获得 Math. Max 可以最长调用的数组长度为 110083,差不多是 11010 的 10 倍(这潜在说明了一个函数调用所需要 Frame 在没有传参的时候大概是 10 个 number 类型长度) 。
U
解决方案 Link to heading
使用自定义 min/max 方法,变 spread 为 loop。
1function arrayMin(arr: number[]) {
2 var len = arr.length,
3 min = Infinity;
4 while (len--) {
5 if (arr[len] < min) {
6 min = arr[len];
7 }
8 }
9 return min;
10}
11
12function arrayMax(arr: number[]) {
13 var len = arr.length,
14 max = -Infinity;
15 while (len--) {
16 if (arr[len] > max) {
17 max = arr[len];
18 }
19 }
20 return max;
21}
经测试有用,且没有了展开运算,性能更高效,使用 lodash 等方案也可以。