Created
January 12, 2014 15:57
-
-
Save cyrilis/8386373 to your computer and use it in GitHub Desktop.
Use ECMAScript 5 in Shit Browsers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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