我在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告诉我这个(这是完全合乎逻辑的):
那么 - 为什么这个检查存在?我在这里错过了什么吗?
不一定 - 这是因为本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]]
,该函数TypeError
在尝试转换时抛出null
或者undefined
),需要执行此检查以满足要求规范.
注意:从技术上讲,你的问题中的代码示例并不完全符合ES5规范,因为该this
值可能是假的,即使它应该在理论上进行也会失败它(indexOf()
如果false
将this
值作为值传递则不抛出的本机实现).同样,由于如果此值实际上未定义或为null,则将传递全局对象,它将通过if (!this)
测试,即使它不应该通过.这不能简单地通过检查参数不是全局对象来解决,因为如果显式传递了全局对象(这是允许的话),这将失败.