如何实现可被Array.prototype.every.call调用的自定义对象?
自定义对象兼容
Array.prototype.every.call的实现方案 当然可以实现这样的自定义对象,Array.prototype.every的核心逻辑依赖类数组结构:即对象拥有length属性,并且能通过非负整数索引(如0、1)访问对应元素。只要满足这个条件,就能被every.call调用并执行断言逻辑。下面分两种场景给出实现方式:
1. 自定义类数组对象
直接创建具备length和索引属性的对象,无需依赖生成器,就能直接被every处理:
// 自定义类数组对象,包含3个元素 const customArrayLike = { length: 3, 0: 's', 1: 's', 2: 't' }; // 调用every断言所有元素为's' const result = Array.prototype.every.call(customArrayLike, n => n === 's'); console.log(result); // 输出 false(第三个元素是't')
2. 生成器转类数组对象
生成器本身是可迭代对象,但不具备length和索引属性,无法直接被every遍历。我们可以将生成器的迭代结果包装成类数组结构:
// 工具函数:将生成器转换为类数组对象 function generatorToArrayLike(generator) { const elements = [...generator]; return { length: elements.length, // 为每个元素添加索引属性 ...elements.reduce((acc, val, idx) => { acc[idx] = val; return acc; }, {}) }; } // 示例生成器:生成三个元素 function* sampleGenerator() { yield 's'; yield 's'; yield 't'; } // 转换后调用every const arrayLikeFromGenerator = generatorToArrayLike(sampleGenerator()); const result = Array.prototype.every.call(arrayLikeFromGenerator, n => n === 's'); console.log(result); // 输出 false
关键原理说明
Array.prototype.every执行时会:
- 获取调用对象的
length属性,确定遍历范围; - 从索引
0到length-1依次访问对象的索引属性; - 对每个元素执行断言回调,一旦有元素不满足就立即返回
false。
只要自定义对象符合这个类数组的结构要求,就能无缝适配every等数组原型方法。
内容的提问来源于stack exchange,提问作者cool_cat
相关产品推荐
相关产品推荐

