JavaScript生成SVG星形多边形时数组规律性出现空项问题
更新位于文末!
SVG一笔画星形多边形生成程序(第一部分)
本程序仅支持单笔绘制完成的星形多边形(如五角星形Pentagram),不支持多图形组合生成的星形(如六角星Hexagram,需2个反向重叠三角形拼接)。
目前程序主体开发接近完成,运行可输出目标结果,但存在已知异常:生成的非因子数组每隔一项就会规律性出现空值,暂未定位原因。
模块功能说明
测试阶段会向控制台输出一个对象:
- 对象的键为数字,对应正多边形的点数/边数
- 每个键对应的值为数组,存储该数字下半区间的所有非因子数值,即键值除以数组内的数结果为分数
输出对象示例
starPolygons { '5': [2], '7': [3,2], '8': [3], '9': [4,2], … }
示例对应含义:正五边形、正七边形、正八边形、正九边形…对应的单笔星形绘制步长参数。
qty_test函数说明
函数接收正多边形点数,计算需要遍历的除数总数量:传入值先除以2,若结果为小数则返回向下取整的值,若结果为整数则返回结果减1。
初始化代码:
// 选8作为示例是因为其需要遍历的除数更多,现象更明显 // 正式遍历逻辑points初始值为5 let points = 8; let starPolygons = {};
函数逻辑示例(传入值为8)
- 传入值8除以2得4
- 判断结果是否为整数
- 是整数则返回4-1=3,是小数则返回结果向下取整的值
原函数代码:
function qty_test(n) { n /= 2; let divisorQTY = n - Math.floor(n) !== 0; return divisorQTY ? Math.floor(n) : (n - 1); };
divisor_test函数说明
函数接收正多边形点数,遍历下半区间的所有除数,收集其中的非因子值存入数组返回。
判断规则:点数除以当前除数结果为小数时,该除数为非因子,存入数组后除数自减1;为整数时该除数是因子,直接跳过,除数自减1。
判断逻辑示例(点数为8)
- 8 / 2 = 4,2是因子,忽略
- 8 / 3 ≈ 2.667,3是非因子,收集
原函数代码:
function divisor_test(n) { let nonFactors = []; n = qty_test(n); for (let index = 0; index <= n; index++) { let quotient = (points / n) - Math.floor(points / n) !== 0; quotient ? nonFactors[index] = n-- : --n; }; return nonFactors; };
遍历逻辑原代码
遍历5到360的所有点数,以点数为键、对应非因子数组为值,构建最终的星形参数对象输出到控制台。
while (points <= 360) { nonFactors = divisor_test(points); let testArray = nonFactors.length; if (testArray) starPolygons[String(points)] = nonFactors; points++; }; console.log(starPolygons);
运行后可观察到数组空索引/空项呈固定规律分布,后续排查发现空槽的分布具备特殊特征,暂未定位成因。
异常原因
数组空槽是JavaScript稀疏数组的典型表现,由两处逻辑错误导致:
- 数组赋值时使用固定自增的
index作为下标,遇到因子跳过赋值时,对应下标位置不会被填充,直接留空 - 循环判断条件
index <= n中的n是动态自减的变量,会导致实际循环次数超出预期,产生多余空索引
额外代码隐患:while循环中的nonFactors变量未声明,会泄露为全局变量;原循环逻辑会遍历到除数为0的情况,触发除零错误,可能引发其他不可预期的问题。
修复代码
移除多余的index计数,收集非因子时直接用push方法追加到数组,除数从计算得到的最大值向下遍历到2即可(1是所有正整数的因子,无需判断,0为非法除数),同时补全变量声明消除全局污染:
function qty_test(n) { n /= 2; return Number.isInteger(n) ? n - 1 : Math.floor(n); } function divisor_test(pointVal) { const nonFactors = []; // 除数从最大值向下遍历到2,避免除零错误、多余循环 let currentDivisor = qty_test(pointVal); while (currentDivisor >= 2) { const isNonFactor = (pointVal / currentDivisor) % 1 !== 0; if (isNonFactor) { nonFactors.push(currentDivisor); } currentDivisor--; } return nonFactors; } // 遍历入口 let points = 5; const starPolygons = {}; while (points <= 360) { const nonFactors = divisor_test(points); if (nonFactors.length) { starPolygons[String(points)] = nonFactors; } points++; } console.log(starPolygons);
修复后输出的数组无空槽,例如点数8对应输出[3],点数9对应输出[4,2],完全符合预期。
更新说明: 原问题中空槽的分布规律本质是:偶数边数的多边形下半区间因子占比高,跳过赋值的位置与赋值位置刚好交替,因此呈现隔一项空一项的现象;奇数边数的多边形因子占比低,空槽出现频率更低,与之前观察到的现象完全吻合。
内容的提问来源于stack exchange,提问作者Eyalchu
相关产品推荐
相关产品推荐

