Skip to content

Instantly share code, notes, and snippets.

@cyrilis
Created January 12, 2014 15:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cyrilis/8386373 to your computer and use it in GitHub Desktop.
Save cyrilis/8386373 to your computer and use it in GitHub Desktop.
Use ECMAScript 5 in Shit Browsers
/**
* Created by Cyril Hou on 14-1-12.
*/
/*
Object.keys fix for IE7, IE8
*/
if (!Object.keys) {
// http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
var hasDontEnumBug = true,
hasProtoEnumBug = (function() {}).propertyIsEnumerable('prototype'),
dontEnums = ["toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "constructor"],
dontEnumsLength = dontEnums.length;
for (var key in {
"toString": null
}) {
hasDontEnumBug = false;
}
Object.keys = function keys(object) {
var isFunction = _toString(object) === '[object Function]',
isObject = object !== null && typeof object === 'object';
if (!isObject && !isFunction) {
throw new TypeError("Object.keys called on a non-object");
}
var keys = [],
skipProto = hasProtoEnumBug && isFunction;
for (var name in object) {
if (!(skipProto && name === 'prototype') && owns(object, name)) {
keys.push(name);
}
}
if (hasDontEnumBug) {
var ctor = object.constructor,
skipConstructor = ctor && ctor.prototype === object;
for (var i = 0; i < dontEnumsLength; i++) {
var dontEnum = dontEnums[i];
if (!(skipConstructor && dontEnum === 'constructor') && owns(object, dontEnum)) {
keys.push(dontEnum);
}
}
}
return keys;
};
}
/*
Trim Prefix For IE
*/
if(typeof String.prototype.trim !== 'function') {
String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g, '');
}
}
/*
Date.now For IE7, IE8
*/
Date.now = Date.now || function() { return +new Date; };
/*
Function.prototype.bind() fix for IE7, IE8
*/
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)));
};
}
};
}
/*
Array.prototype.indexOf() fix for IE7, IE8
*/
if (!('indexOf' in Array.prototype)) {
Array.prototype.indexOf= function(find, i) {
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;
};
}
/*
Array.prototype.lastIndexOf() fix for IE7, IE8
*/
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;
};
}
/*
Array.prototype.forEach() fix for IE7, IE8
*/
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);
};
}
/*
Array.prototype.map() fix for IE7, IE8
*/
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;
};
}
/*
Array.prototype.filter() fix for IE7, IE8
*/
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;
};
}
/*
Array.prototype.every() fix for IE7, IE8
*/
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;
};
}
/*
Array.prototype.every() fix for IE7, IE8
*/
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;
};
}
/*
Array.prototype.reduce() fix for IE7, IE8
*/
if (!Array.prototype.reduce) {
Array.prototype.reduce = function reduce(fun /*, initial*/ ) {
var object = toObject(this),
self = splitString && _toString(this) == "[object String]" ? this.split("") : object,
length = self.length >>> 0;
if (_toString(fun) != "[object Function]") {
throw new TypeError(fun + " is not a function");
}
if (!length && arguments.length == 1) {
throw new TypeError("reduce of empty array with no initial value");
}
var i = 0;
var result;
if (arguments.length >= 2) {
result = arguments[1];
} else {
do {
if (i in self) {
result = self[i++];
break;
}
if (++i >= length) {
throw new TypeError("reduce of empty array with no initial value");
}
} while (true);
}
for (; i < length; i++) {
if (i in self) {
result = fun.call(void 0, result, self[i], i, object);
}
}
return result;
};
}
/*
Array.isArray() fix for IE7, IE8
*/
if (!Array.isArray) {
Array.isArray = function isArray(obj) {
return _toString(obj) == "[object Array]";
};
}
/*
Array.prototype.reduceRight() fix for IE7, IE8
*/
if (!Array.prototype.reduceRight) {
Array.prototype.reduceRight = function reduceRight(fun /*, initial*/ ) {
var object = toObject(this),
self = splitString && _toString(this) == "[object String]" ? this.split("") : object,
length = self.length >>> 0;
if (_toString(fun) != "[object Function]") {
throw new TypeError(fun + " is not a function");
}
if (!length && arguments.length == 1) {
throw new TypeError("reduceRight of empty array with no initial value");
}
var result, i = length - 1;
if (arguments.length >= 2) {
result = arguments[1];
} else {
do {
if (i in self) {
result = self[i--];
break;
}
// if array contains no values, no initial value to return
if (--i < 0) {
throw new TypeError("reduceRight of empty array with no initial value");
}
} while (true);
}
if (i < 0) {
return result;
}
do {
if (i in this) {
result = fun.call(void 0, result, self[i], i, object);
}
} while (i--);
return result;
};
}
/*
Number.prototype.toFixed() fix for IE7, IE8
*/
if (!Number.prototype.toFixed || (0.00008).toFixed(3) !== '0.000' || (0.9).toFixed(0) === '0' || (1.255).toFixed(2) !== '1.25' || (1000000000000000128).toFixed(0) !== "1000000000000000128") {
// Hide these variables and functions
(function() {
var base, size, data, i;
base = 1e7;
size = 6;
data = [0, 0, 0, 0, 0, 0];
function multiply(n, c) {
var i = -1;
while (++i < size) {
c += n * data[i];
data[i] = c % base;
c = Math.floor(c / base);
}
}
function divide(n) {
var i = size,
c = 0;
while (--i >= 0) {
c += data[i];
data[i] = Math.floor(c / n);
c = (c % n) * base;
}
}
function toString() {
var i = size;
var s = '';
while (--i >= 0) {
if (s !== '' || i === 0 || data[i] !== 0) {
var t = String(data[i]);
if (s === '') {
s = t;
} else {
s += '0000000'.slice(0, 7 - t.length) + t;
}
}
}
return s;
}
function pow(x, n, acc) {
return (n === 0 ? acc : (n % 2 === 1 ? pow(x, n - 1, acc * x) : pow(x * x, n / 2, acc)));
}
function log(x) {
var n = 0;
while (x >= 4096) {
n += 12;
x /= 4096;
}
while (x >= 2) {
n += 1;
x /= 2;
}
return n;
}
Number.prototype.toFixed = function(fractionDigits) {
var f, x, s, m, e, z, j, k;
// Test for NaN and round fractionDigits down
f = Number(fractionDigits);
f = f !== f ? 0 : Math.floor(f);
if (f < 0 || f > 20) {
throw new RangeError("Number.toFixed called with invalid number of decimals");
}
x = Number(this);
// Test for NaN
if (x !== x) {
return "NaN";
}
// If it is too big or small, return the string value of the number
if (x <= -1e21 || x >= 1e21) {
return String(x);
}
s = "";
if (x < 0) {
s = "-";
x = -x;
}
m = "0";
if (x > 1e-21) {
// 1e-21 < x < 1e21
// -70 < log2(x) < 70
e = log(x * pow(2, 69, 1)) - 69;
z = (e < 0 ? x * pow(2, -e, 1) : x / pow(2, e, 1));
z *= 0x10000000000000; // Math.pow(2, 52);
e = 52 - e;
// -18 < e < 122
// x = z / 2 ^ e
if (e > 0) {
multiply(0, z);
j = f;
while (j >= 7) {
multiply(1e7, 0);
j -= 7;
}
multiply(pow(10, j, 1), 0);
j = e - 1;
while (j >= 23) {
divide(1 << 23);
j -= 23;
}
divide(1 << j);
multiply(1, 1);
divide(2);
m = toString();
} else {
multiply(0, z);
multiply(1 << (-e), 0);
m = toString() + '0.00000000000000000000'.slice(2, 2 + f);
}
}
if (f > 0) {
k = m.length;
if (k <= f) {
m = s + '0.0000000000000000000'.slice(0, f - k + 2) + m;
} else {
m = s + m.slice(0, k - f) + '.' + m.slice(k - f);
}
} else {
m = s + m;
}
return m;
}
}());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment