我看到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向我展示了这一点(这是完全合乎逻辑的):
那么 - 为什么这个检查存在?我在这里错过了什么吗?
答案 0 :(得分:7)
不一定 - 这是因为indexOf()
本机函数使用传递的直接this
值,而不是转换为对象的值(相当于严格模式下发生的值),这样的垫片会需要检查这是否合规。例如,此代码将抛出TypeError
:
var a = Array.prototype.indexOf;
a();
它将抛出TypeError
,因为this
值未转换为对象或更改为全局对象。在用户定义的非严格函数中,如果没有父对象,则this
的值是全局对象,但在ES5严格模式下,它本身作为undefined
传递。另一种情况是,您使用null
或undefined
专门致电:
"use strict";
Array.prototype.indexOf.call(null); // TypeError, what else can we do?
在ES5规范中, 此值指的是作为thisArg
传递的原始值,没有任何更改。在非严格模式下,用户定义函数中的代码无法访问 此值,但本机函数能够明确指定使用 >此值而不是this
关键字的计算结果(在规范中称为ThisBinding
)。在严格模式下,他们都评价同样的事情。
因为本机版本能够以非严格模式访问this
值的非盒装版本(它直接传递给内部函数[[ToObject]]
,后者抛出{{1}在尝试转换TypeError
或null
)时,需要执行此检查以满足规范的要求。
注意:从技术上讲,问题中的代码示例不是ES5规范的完全,因为undefined
值可能是假的,即使它应该继续也会失败理论上(如果this
作为indexOf()
值传递,则false
的本机实现不会抛出。同样,因为如果此值实际上未定义或为null,则传递全局对象,它将通过this
测试,即使它不应该。这不能简单地通过检查参数不是全局对象来解决,因为如果显式传递了全局对象(这是允许的话),这将失败。