Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
polyfill an ES5-compatibile Array.prototype.lastIndexOf where needed.

Polyfill for ES5: Array.prototype.lastIndexOf

A tweet-sized ES5-compatible polyfill for Array.prototype.lastIndexOf based on a similar function in my own tiny.js

// avoid overwriting Array.prototype.lastIndexOf
// otherwise it becomes enumerable, which leads to
// errors in Chrome
[].lastIndexOf || (Array.prototype.lastIndexOf = function(
a, // item to be found
b // index placeholder
) {
for (
// initialize index
b=this.length;
// if the index decreased by one is not already -1
// index is not set (sparse array)
// and the item at index is not identical to the searched one
~--b && (!(b in a) || this[b] !== a););
// return index of last found item or -1
return b
})
[].lastIndexOf||(Array.prototype.lastIndexOf=function(a,b){for(b=this.length;~--b&&(!(b in a)||this[b]!==a););return b})
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2011 Alex Kloss <alexthkloss@web.de>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "lastIndexOf",
"description": "polyfill an ES5-compatibile Array.prototype.lastIndexOf where needed.",
"keywords": [
"array",
"lastIndexof",
"es5",
"polyfill"
]
}
<!DOCTYPE html>
<title>Foo</title>
<div>Expected value: <b>0,1,2,-1</b></div>
<div>Actual value: <b id="ret"></b></div>
<script>
var lastIndexOf =
[].lastIndexOf||(Array.prototype.lastIndexOf=function(a,b){for(b=this.length;~--b&&(!(b in a)||this[b]!==a););return b})
var testdata=[1,2,3,5];
document.getElementById( "ret" ).innerHTML = [lastIndexOf.call(testdata,1), lastIndexOf.call(testdata,2), lastIndexOf.call(testdata,3), lastIndexOf.call(testdata,4)];
</script>
@wrayal

This comment has been minimized.

Show comment Hide comment
@wrayal

wrayal Jun 20, 2011

Can I ask a stupid question here? What is the exact function of !== (as opposed to !=)? I mean, I guess it negates == but I'm not clear on the exact differences - could you clarify at all?

wrayal commented Jun 20, 2011

Can I ask a stupid question here? What is the exact function of !== (as opposed to !=)? I mean, I guess it negates == but I'm not clear on the exact differences - could you clarify at all?

@atk

This comment has been minimized.

Show comment Hide comment
@atk

atk Jun 20, 2011

No question is ever stupid, only the notion that it could be is. !== is the opposite of ===, meaning a typesafe not equal comparison: if the types and the compared objects are the same, it yields false. If one "=" was omitted, the comparison would not be typesafe anymore, so same values of different types, e.g. 0 != "0" would be false while 0 !== "0" was true.

Owner

atk commented Jun 20, 2011

No question is ever stupid, only the notion that it could be is. !== is the opposite of ===, meaning a typesafe not equal comparison: if the types and the compared objects are the same, it yields false. If one "=" was omitted, the comparison would not be typesafe anymore, so same values of different types, e.g. 0 != "0" would be false while 0 !== "0" was true.

@jed

This comment has been minimized.

Show comment Hide comment
@jed

jed Jul 11, 2011

hey @atk, could you fix your package.json here too?

jed commented Jul 11, 2011

hey @atk, could you fix your package.json here too?

@jdalton

This comment has been minimized.

Show comment Hide comment
@jdalton

jdalton Aug 21, 2011

Despite the description, polyfill an ES5-compatibile Array.prototype.lastIndexOf where needed., this is not an ES5 compatible fallback because it lacks sparse array support and resolves the length incorrectly. Also browsers like Chrome have a bug where Array.prototype.lastIndexOf = [].lastIndexOf will cause Array#lastIndexOf to become enumerable.

jdalton commented Aug 21, 2011

Despite the description, polyfill an ES5-compatibile Array.prototype.lastIndexOf where needed., this is not an ES5 compatible fallback because it lacks sparse array support and resolves the length incorrectly. Also browsers like Chrome have a bug where Array.prototype.lastIndexOf = [].lastIndexOf will cause Array#lastIndexOf to become enumerable.

@tsaniel

This comment has been minimized.

Show comment Hide comment
@tsaniel

tsaniel Dec 5, 2011

Seems we don't need b?

function(a,c){for(c=this.length;this[--c]!==a&&~c;);return c}

tsaniel commented Dec 5, 2011

Seems we don't need b?

function(a,c){for(c=this.length;this[--c]!==a&&~c;);return c}
@atk

This comment has been minimized.

Show comment Hide comment
@atk

atk Dec 5, 2011

Now we have as much ES5-compatibility as possible; the length is resolved correctly, sparse arrays are taken care of and the Chrome bug is resolved by the more secure shim logic.

Owner

atk commented Dec 5, 2011

Now we have as much ES5-compatibility as possible; the length is resolved correctly, sparse arrays are taken care of and the Chrome bug is resolved by the more secure shim logic.

@jdalton

This comment has been minimized.

Show comment Hide comment
@jdalton

jdalton Dec 5, 2011

This is still missing fromIndex support.

jdalton commented Dec 5, 2011

This is still missing fromIndex support.

@tsaniel

This comment has been minimized.

Show comment Hide comment
@tsaniel

tsaniel Dec 5, 2011

What about

function(a,b){for(++b>0?0:b=this.length+~~b;~--b&&(!(b in this)||this[b]!==a););return b}

?

Updated.

tsaniel commented Dec 5, 2011

What about

function(a,b){for(++b>0?0:b=this.length+~~b;~--b&&(!(b in this)||this[b]!==a););return b}

?

Updated.

@tsaniel

This comment has been minimized.

Show comment Hide comment
@tsaniel

tsaniel Dec 5, 2011

I think it still has room to be shortened.

tsaniel commented Dec 5, 2011

I think it still has room to be shortened.

@atk

This comment has been minimized.

Show comment Hide comment
@atk

atk Dec 9, 2011

@tsaniel: nice one! I think that'll work!

Owner

atk commented Dec 9, 2011

@tsaniel: nice one! I think that'll work!

@tsaniel

This comment has been minimized.

Show comment Hide comment
@tsaniel

tsaniel Dec 9, 2011

By the way, i wonder if

[].lastIndexOf||(Array.prototype.lastIndexOf=...)

and

[].lastIndexOf?0:Array.prototype.lastIndexOf=...

are equal.

tsaniel commented Dec 9, 2011

By the way, i wonder if

[].lastIndexOf||(Array.prototype.lastIndexOf=...)

and

[].lastIndexOf?0:Array.prototype.lastIndexOf=...

are equal.

@jdalton

This comment has been minimized.

Show comment Hide comment
@jdalton

jdalton Dec 9, 2011

@tsaniel It's not clamping the fromIndex correctly:

5: If argument fromIndex was passed let n be ToInteger(fromIndex); else let n be len.
6: If n ≥ 0, then let k be min(n, len – 1).
7: Else, n < 0
---- a. Let k be len - abs(n).

jdalton commented Dec 9, 2011

@tsaniel It's not clamping the fromIndex correctly:

5: If argument fromIndex was passed let n be ToInteger(fromIndex); else let n be len.
6: If n ≥ 0, then let k be min(n, len – 1).
7: Else, n < 0
---- a. Let k be len - abs(n).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment