严格模式下JavaScript indexOf()方法返回意外结果的原因咨询
[0,1].indexOf(0)会返回-1? 嘿,这个问题其实不是原生JavaScript的bug,核心原因和你猜测的完全一致——老旧的indexOf Polyfill在严格模式下对this的处理存在漏洞,我来给你拆解清楚:
先明确一个关键前提
原生的Array.prototype.indexOf在严格模式和非严格模式下的表现完全一致:[0,1].indexOf(0)肯定会返回0,这是ECMAScript标准明确规定的行为,不存在所谓的“严格模式专属bug”。
问题根源:旧版MDN Polyfill的缺陷
你提到的MDN旧版Polyfill(现在已经更新修复),存在一个严格模式下的逻辑漏洞:
当Polyfill执行时,如果this指向undefined(严格模式下,函数调用时若未指定this,不会自动绑定到全局对象window),代码里的Object(this)会把undefined转换为一个空对象{}。
这个空对象的length属性是undefined,经过len = O.length >>> 0的无符号右移转换后,会变成0。此时Polyfill会直接返回-1,因为它判定这个“数组”的长度为0,自然找不到任何元素。
而非严格模式下,this会自动绑定到window,Object(window)的length不为0,Polyfill会继续遍历查找,最终返回正确的索引0——这就是你看到两种模式结果差异的核心原因。
怎么验证这个逻辑?
如果你用的是新版MDN Polyfill,这个问题已经被修复:新版Polyfill会先通过var O = Object(this)确保this被转为对象,再处理长度,同时兼容this不是数组的场景。关键是,当你通过数组实例正常调用indexOf时,this本来就是数组对象,所以无论严格与否,都会正常工作。
只有当你把indexOf方法从数组实例上分离出来单独调用(比如var fn = [0,1].indexOf; fn(0)),且处于严格模式下时,旧Polyfill才会返回-1——这时候this是undefined,刚好触发了那个漏洞。
总结
- 原生
indexOf无此问题,严格/非严格模式表现完全一致; - 问题源于旧版Polyfill对严格模式下
this为undefined的场景处理不当; - 现在的标准Polyfill已经修复了这个问题,建议使用更新后的版本。
内容的提问来源于stack exchange,提问作者wwwebman

