Javascript indexOf shim澄清?

时间:2013-12-03 14:37:46

标签: javascript arrays indexof

我看到at mdn应该使用的代码 - 如果没有indexOf实现。

此算法与ECMA-262 中指定的算法相匹配......正如他们所说

以下是代码:

/*1*/   if (!Array.prototype.indexOf) {
/*2*/     Array.prototype.indexOf = function (searchElement , fromIndex) {
/*3*/       var i,
/*4*/           pivot = (fromIndex) ? fromIndex : 0,
/*5*/           length;
/*6*/   
/*7*/       if (!this) {
/*8*/         throw new TypeError();
/*9*/       }
/*10*/   
/*11*/       length = this.length;
/*12*/   
/*13*/       if (length === 0 || pivot >= length) {
/*14*/         return -1;
/*15*/       }
/*16*/   
/*17*/       if (pivot < 0) {
/*18*/         pivot = length - Math.abs(pivot);
/*19*/       }
/*20*/   
/*21*/       for (i = pivot; i < length; i++) {
/*22*/         if (this[i] === searchElement) {
/*23*/           return i;
/*24*/         }
/*25*/       }
/*26*/       return -1;
/*27*/     };
/*28*/   }

但我的问题是关于第7行:

如果我写:

[].indexOf然后 - this是数组本身。 (哎呀,它首先附在Array.prototype.indexOf上)。

我的意思是 - this永远是真正的价值。那么为什么这个检查是否存在?

此外 - Resharper向我展示了这一点(这是完全合乎逻辑的):

enter image description here

那么 - 为什么这个检查存在?我在这里错过了什么吗?

1 个答案:

答案 0 :(得分:7)

不一定 - 这是因为indexOf()本机函数使用传递的直接this值,而不是转换为对象的值(相当于严格模式下发生的值),这样的垫片会需要检查这是否合规。例如,此代码将抛出TypeError

var a = Array.prototype.indexOf;
a();

它将抛出TypeError,因为this值未转换为对象或更改为全局对象。在用户定义的非严格函数中,如果没有父对象,则this的值是全局对象,但在ES5严格模式下,它本身作为undefined传递。另一种情况是,您使用nullundefined专门致电:

"use strict";
Array.prototype.indexOf.call(null); // TypeError, what else can we do?

在ES5规范中, 指的是作为thisArg传递的原始值,没有任何更改。在非严格模式下,用户定义函数中的代码无法访问 ,但本机函数能够明确指定使用 >此而不是this关键字的计算结果(在规范中称为ThisBinding)。在严格模式下,他们都评价同样的事情。

因为本机版本能够以非严格模式访问this值的非盒装版本(它直接传递给内部函数[[ToObject]],后者抛出{{1}在尝试转换TypeErrornull)时,需要执行此检查以满足规范的要求。

注意:从技术上讲,问题中的代码示例不是ES5规范的完全,因为undefined值可能是假的,即使它应该继续也会失败理论上(如果this作为indexOf()值传递,则false的本机实现不会抛出。同样,因为如果此值实际上未定义或为null,则传递全局对象,它将通过this测试,即使它不应该。这不能简单地通过检查参数不是全局对象来解决,因为如果显式传递了全局对象(这是允许的话),这将失败。