如何在JavaScript中创建数组属性?及实现区间唯一随机整数生成函数
问题1:在JavaScript中创建数组作为属性的方法
其实有好几种简单直观的方式来实现,我给你列几个常用场景:
- 对象字面量直接定义:创建对象时直接把数组作为属性值写入,是最常用的方式:
const myObj = { fruits: ['apple', 'banana', 'orange'], // 直接定义数组属性 scores: [90, 85, 95] }; console.log(myObj.fruits); // 输出: ['apple', 'banana', 'orange']
- 动态给已有对象添加:如果对象已经存在,随时可以为它新增数组属性:
const pet = {}; pet.toys = ['ball', 'rope', 'mouse']; // 动态挂载数组属性 console.log(pet.toys); // 输出: ['ball', 'rope', 'mouse']
- 构造函数内初始化:用构造函数创建对象时,可在内部为
this添加数组属性:
function Player(name) { this.name = name; this.achievements = []; // 初始化空数组属性 } const zhangsan = new Player('张三'); zhangsan.achievements.push('首次通关'); console.log(zhangsan.achievements); // 输出: ['首次通关']
另外你在问题2里写的generateUniqueInt.used = new Array;,本质也是给函数对象添加数组属性——因为JavaScript里函数本身也是对象,所以直接给函数挂载属性完全可行。
问题2:改进生成唯一随机整数的函数
你的核心思路没问题:用函数的属性记录已生成的数来避免重复。不过这个实现有两个需要优化的点:
- 无限循环风险:当调用次数超过100次(你的区间是0-99),
while循环会一直找不到未使用的数,陷入死循环; - 性能瓶颈:当已生成的数接近100个时,
indexOf的查找和循环重试的概率会越来越高,效率下降明显。
我给你两种优化方案,适配不同场景:
方案1:预生成洗牌池(高效稳定)
先把区间内所有数生成并打乱,每次调用直接从池子里取最后一个数,彻底避免循环重试:
function generateUniqueInt(min = 0, max = 99) { // 首次调用时初始化洗牌池 if (!generateUniqueInt.pool) { generateUniqueInt.pool = []; // 生成min到max的所有整数 for (let i = min; i <= max; i++) { generateUniqueInt.pool.push(i); } // 用Fisher-Yates洗牌算法打乱数组(公平且高效) for (let i = generateUniqueInt.pool.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [generateUniqueInt.pool[i], generateUniqueInt.pool[j]] = [generateUniqueInt.pool[j], generateUniqueInt.pool[i]]; } } // 取最后一个元素,池空时返回undefined(可按需改成抛错或重置) return generateUniqueInt.pool.pop(); } // 测试调用20次 for (let i = 0; i < 20; i++) { console.log(generateUniqueInt()); }
这个方案的优势:随机公平、性能稳定、支持自定义区间,适合区间范围不大的场景。
方案2:用Set优化查找(适合大区间场景)
如果你的区间范围极大(比如0到10000),预生成所有数太占内存,那可以用Set替代数组存储已使用的数——Set.has()的查找速度远快于数组indexOf(),同时加上边界检查避免死循环:
function generateUniqueInt(min = 0, max = 99) { // 首次调用时初始化Set if (!generateUniqueInt.used) { generateUniqueInt.used = new Set(); } // 检查是否还有可用数 if (generateUniqueInt.used.size >= (max - min + 1)) { throw new Error('所有可能的整数都已生成完毕'); } let res; do { res = Math.floor(Math.random() * (max - min + 1)) + min; } while (generateUniqueInt.used.has(res)); generateUniqueInt.used.add(res); return res; }
这个方案保留了你原有的“按需生成”思路,同时解决了性能和死循环问题。
内容的提问来源于stack exchange,提问作者Matus Dubrava
相关产品推荐
相关产品推荐

