Question

I saw at mdn the code which should be used - if there is no indexOf implementation .

This algorithm matches the one specified in ECMA-262 ... as they say

And here is the code :

/*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*/   }

But my question is about line #7 :

If I write :

[].indexOf then - this is the array itself. ( Heck , it is attached to Array.prototype.indexOf - at first place).

I mean - this will always be truthy value. so why does this check exist ?

Also - Resharper shows me this ( which is perfectly logical) :

enter image description here

So - why does this check exist? Am I missing something here ?

Was it helpful?

Solution

Not necessarily -- it's because the indexOf() native function uses the direct this value passed, not the one converted to an object (equivalent to what happens in strict mode), and such a shim would need to check for this to be compliant. For example, this code will throw a TypeError:

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

It will throw a TypeError, as the this value is not converted into an object or changed to the global object. In user-defined non-strict functions, the value of this is the global object if there is no parent object, but in ES5 strict mode it is passed as undefined itself. Another situation is when you call it specifically with either null or undefined:

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

In the ES5 specification, the this value refers to the original value passed as the thisArg, without any changes. In non-strict mode, the this value is not accessible to code in user-defined functions, but native functions are able to explicitly specify use of the this value instead of what the this keyword evaluates to (which is referred to as the ThisBinding in the specification). In strict mode, they both evaluate to the same thing.

Because the native version is able to access the non-boxed version of the this value in non-strict mode (which is directly passed to the internal function [[ToObject]], which throws a TypeError upon attempting to convert null or undefined), this check needs to implemented to satisfy the requirements of the specification.

Note: technically, the code sample in your question isn't quite by the ES5 specification, as the this value could be falsy, which would fail it even though it should proceed in theory (native implementations of indexOf() do not throw if false is passed as the this value). As well, since the global object would be passed if the this value was actually undefined or null, it would pass the if (!this) test, even when it's not supposed to. This cannot be solved simply by checking that the argument is not the global object, because this would fail if the global object was explicitly passed (which is permitted).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top