Execute an expression for every element in an array and determine whether one of the elements make the expression evaluate truthy. This polyfill adds the some
method to the array prototype for environments lower than ECMAScript 5.
-
-
Save eliperelman/1037838 to your computer and use it in GitHub Desktop.
Array.prototype.some = [].some || // Use the native every method if available, otherwise: | |
function ( | |
a, // expression to test each element of the array against | |
b, // optionally change the 'this' context for the given callback | |
c, // placeholder iterator variable | |
d // placeholder variable (stores context of original array) | |
) { | |
for (c = 0, d = this; c < d.length; c++) // iterate over all of the array elements | |
if (a.call(b, d[c], c, d)) // call the given expression, passing in context, value, index, and original array | |
return !0; // if any expression evaluates true, immediately return since 'some' is true | |
return !1 // otherwise return false since all callbacks evaluated to false | |
} |
Array.prototype.some=[].some||function(a,b,c,d){for(c=0,d=this;c<d.length;c++)if(a.call(b,d[c],c,d))return!0;return!1} |
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE | |
Version 2, December 2004 | |
Copyright (C) 2011 Eli Perelman <http://eliperelman.com> | |
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": "ArrayPrototypeSomePolyfill", | |
"description": "Array some polyfill method for ECMAScript versions older than 5.", | |
"keywords": [ | |
"Array", | |
"prototype", | |
"some", | |
"polyfill", | |
"ecmascript5" | |
] | |
} |
<!DOCTYPE html> | |
<title>Array.prototype.some polyfill</title> | |
<script> | |
Array.prototype.some=[].some||function(a,b,c,d){for(c=0,d=this;c<d.length;c++)if(a.call(b,d[c],c,d))return!0;return!1} | |
var arr = [2,4,6,8,10,12,14,16]; | |
var arr2 = [1,2,3,4,5,6,7,8]; | |
// logs true, since at least 'some' elements are less than 10 | |
console.log(arr.some(function(value, index, myArray) { | |
return value < 10; | |
}); | |
// logs false, since none of the values are greater than 20 or none of arr2 values are greater than 10 | |
console.log(arr.some(function(value, index, myArray) { | |
// this refers to arr2, but myArray is still arr | |
return this[index] > 10 || value > 20; | |
}, arr2); | |
</script> |
And if the order of elements within the array doesn't matter, we can make this even shorter:
Array.prototype.some=[].some||function(a,b,c,d,e){for(d=this,c=d.length;c--;)if(a.call(b,d[c],c,d))e=1;return!!e}
Very nice! I will update with your changes.
Hmm, the one issue with this is that is doesn't return immediately after the first truthy expression is run. I wonder if the shorter bytes is worth the performance hit.
Issue valid. My Suggestion: keep both variants.
This fallback is not ES5 complaint.
Also browsers like Chrome have a bug where Array.prototype.some = [].some
will cause Array#some
to become enumerable.
I would prefer a less dangerous version like [].some||(Array.prototype.some=function(){}), too. Yet I do not see why in hell this fallback should be a complaint. Unless, of course, you just let off some freudian slip on your own complaint about it not being compliant - which it probably is in three ways: 1. does not check hasOwnProperty - which shouldn't do anything in modern browsers unless you play too much with prototypes - and if that is the case, shame on you, 2. doesn't replace b with d if not present, 3. may not have a length property of 1.
Anyway: If you can provide a better version within 140bytes, feel free to do so.
Yet I do not see why in hell this fallback should be a complaint.
Fallbacks should be compliant with ES5 because you are modifying the Array.prototype and other scirpts after may assume that a fully functional and complaint method exists. By not following spec you create an inconsistency in use between browsers that do and don't support the native method.
Anyway: If you can provide a better version within 140bytes, feel free to do so.
I don't think ES5 fallbacks are the best choice for code golf in general because things should be really tight and follow spec as these methods are added to native prototypes.
RFC 1925, 1: "It has to work." - This is true for polyfills as well.
@atk see my comment on Function#bind.
For more information on what can be changed to make this method ES5 compliant and info on a critical bug, that this gist shares, please see my comments on a similar Array#filter
gist.
Taking care of sparse arrays while also saving space (77bytes left):
[].some||(Array.prototype.some=function(a,b,c,d){d=this;for(c in d)if(a.call(b,d[c],c,d))return!0;return!1})
Disclaimer: If you want to have it all secured against prototype madness, you can throw in a hasOwnProperty check.
@atk nice, lots of space left for smth like (115 bytes):
[].some||(Array.prototype.some=function(a,b,c,d){d=this;for(c in d)if(c==+c&&a.call(b,d[c],c,d))return!0;return!1})
which would avoid most problem keys but still allow keys like "03"
... OR (125 bytes)
[].some||(Array.prototype.some=function(a,b,c,d){d=this;for(c in d)if(~~c+''==c&&c>-1&&a.call(b,d[c],c,d))return!0;return!1})
which should avoid that edge case issue.
Saving some additional bytes: