Skip to content

Instantly share code, notes, and snippets.

@jonlabelle
Last active January 27, 2019 00:21
Show Gist options
  • Select an option

  • Save jonlabelle/11159210 to your computer and use it in GitHub Desktop.

Select an option

Save jonlabelle/11159210 to your computer and use it in GitHub Desktop.
JavaScript Shims
/**
* Many use the MDC fallback implementations (eg. for
* [indexOf](http://goo.gl/SIyI35)). They're generally rigorously
* standards-compliant, even to the extent of explicitly checking the types of
* all the arguments.
*
* Unfortunately whilst it is clear that the authors regard this code as
* trivial and freely-usable, there doesn't seem to be an explicit
* licence-grant to put this in writing. The wiki as a whole is CC
* Attribution-ShareAlike, if that's an acceptable licence (though CC isn't
* designed for code as such).
*
* js-methods looks OK in general, but is not as standards-compliant around
* the edges of how the functions are supposed to be (eg. undefined list
* items, functions that mutate the list). It's also full of other random
* non-standard methods, including some questionable ones like the dodgy
* stripTags and the incomplete UTF-8 codec (which is also a bit unnecessary
* given the unescape(encodeURIComponent) trick).
*
* For what it's worth, here's what I use (which I hereby release into the
* public domain, if it can be said to be copyrightable at all). It's a bit
* shorter than the MDC versions as it doesn't attempt to type-sniff that you
* haven't done something silly like pass non-function callbacks or
* non-integer indexes, but apart from that it attempts to be
* standards-compliant. (Let me know if I've missed anything. ;-))
*
* Resources
*
* - Stackoverflow: "Fixing JavaScript Array functions in Internet Explorer
* (indexOf, forEach, etc.)" http://goo.gl/1wibE
*
* - JavaScript prototype extensions
* https://code.google.com/p/js-methods/
*/
"use strict";
// Add ECMA262-5 method binding if not supported natively
//
if (!("bind" in Function.prototype)) {
Function.prototype.bind = function(owner) {
var that = this;
if (arguments.length <= 1) {
return function() {
return that.apply(owner, arguments);
};
} else {
var args = Array.prototype.slice.call(arguments, 1);
return function() {
return that.apply(
owner,
arguments.length === 0
? args
: args.concat(Array.prototype.slice.call(arguments))
);
};
}
};
}
// Add ECMA262-5 string trim if not supported natively
//
if (!("trim" in String.prototype)) {
String.prototype.trim = function() {
return this.replace(/^\s+/, "").replace(/\s+$/, "");
};
}
// Add ECMA262-5 Array methods if not supported natively
//
if (!("indexOf" in Array.prototype)) {
Array.prototype.indexOf = function(find, i /*opt*/) {
if (i === undefined) i = 0;
if (i < 0) i += this.length;
if (i < 0) i = 0;
for (var n = this.length; i < n; i++)
if (i in this && this[i] === find) return i;
return -1;
};
}
if (!("lastIndexOf" in Array.prototype)) {
Array.prototype.lastIndexOf = function(find, i /*opt*/) {
if (i === undefined) i = this.length - 1;
if (i < 0) i += this.length;
if (i > this.length - 1) i = this.length - 1;
for (i++; i-- > 0 /* i++ because from-argument is sadly inclusive */; )
if (i in this && this[i] === find) return i;
return -1;
};
}
if (!("forEach" in Array.prototype)) {
Array.prototype.forEach = function(action, that /*opt*/) {
for (var i = 0, n = this.length; i < n; i++)
if (i in this) action.call(that, this[i], i, this);
};
}
if (!("map" in Array.prototype)) {
Array.prototype.map = function(mapper, that /*opt*/) {
var other = new Array(this.length);
for (var i = 0, n = this.length; i < n; i++)
if (i in this) other[i] = mapper.call(that, this[i], i, this);
return other;
};
}
if (!("filter" in Array.prototype)) {
Array.prototype.filter = function(filter, that /*opt*/) {
var other = [],
v;
for (var i = 0, n = this.length; i < n; i++)
if (i in this && filter.call(that, (v = this[i]), i, this))
other.push(v);
return other;
};
}
if (!("every" in Array.prototype)) {
Array.prototype.every = function(tester, that /*opt*/) {
for (var i = 0, n = this.length; i < n; i++)
if (i in this && !tester.call(that, this[i], i, this)) return false;
return true;
};
}
if (!("some" in Array.prototype)) {
Array.prototype.some = function(tester, that /*opt*/) {
for (var i = 0, n = this.length; i < n; i++)
if (i in this && tester.call(that, this[i], i, this)) return true;
return false;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment