Created
July 29, 2012 22:06
-
-
Save Skateside/3202105 to your computer and use it in GitHub Desktop.
I've been looking at Sugar and RightJS and I figured I'd start playing with my own version. I like what these things do to the language, they make it seem a lot more sensible. Ultimately this would add the ES5 and ES6 methods as well as some more new ones
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
// This is very similar to the standard implimentation of Object.extend but the | |
// important difference here is that this method will not overwrite any existing | |
// method of the source object. This makes it idea for updating native objects. | |
if (!Object.hasOwnProperty('update')) { | |
(function () { | |
'use strict'; | |
var setProp = function (source, property, value) { | |
Object.defineProperty(source, property, { | |
value: value, | |
enumarable: false | |
}); | |
}; | |
function definePropertyWorks() { | |
var obj = {}, | |
works = false; | |
try { | |
Object.defineProperty(obj, 'sk80', {}); | |
works = obj.hasOwnProperty('sk80'); | |
} catch (e) { | |
} | |
return works; | |
} | |
if (!definePropertyWorks()) { | |
setProp = function (source, property, value) { | |
source[property] = value; | |
}; | |
} | |
Object.update = function (source, update) { | |
var property; | |
for (property in update) { | |
if (update.hasOwnProperty(property) | |
&& !source.hasOwnProperty(property)) { | |
setProp(source, property, update[property]); | |
} | |
} | |
return source; | |
}; | |
}()); | |
} | |
Object.update(Number.prototype, (function () { | |
'use strict'; | |
var undef, | |
// These bizare-looking variable statements allows us to minify some of the | |
// global variables that we use in this function. | |
Math = window.Math, | |
isFinite = window.isFinite; | |
// Extends an object with another object. Each key in the object is checked to | |
// make sure that it does not exist in the source object before it is added. | |
// | |
// Takes: | |
// source {Object} The source Object to extend. | |
// extra {Object} The extra keys to add to the source. | |
// | |
// Returns: | |
// {Object} The extended Object. | |
function extend(source, extra) { | |
var i; | |
for (i in extra) { | |
if (extra.hasOwnProperty(i) && !source.hasOwnProperty(i)) { | |
source[i] = extra[i]; | |
} | |
} | |
return source; | |
} | |
// Creates an absolute value of a given number. Since it converts a number using | |
// parseInt, this function will also work with numeric strings. | |
// | |
// Takes: | |
// number {Mixed} Hopefully either a Number or a numeric String. | |
// | |
// Returns: | |
// {Number} An absolute value of the given number, or NaN if | |
// number was not numeric. | |
function absNumber(number) { | |
return parseInt(number).abs(); | |
} | |
// A few places in the ECMAScript specifications says: | |
// "Let posInt be sign(number) * floor(abs(number))" | |
// Since it's used a few times, we may as well make a function to aid | |
// minification and prevent us repeating ourselves. | |
// I know it has the potential to return a negative integer, that's always | |
// bugged me about the specs. | |
// | |
// Takes: | |
// number {Number} The number to convert into a positive integer. | |
// | |
// Returns: | |
// {Number} The positive integer, or NaN if number was not | |
// numeric. | |
function posInt(number) { | |
return number.sign() * number.abs().floor(); | |
} | |
return { | |
// A simple mapping of Math.pow. | |
pow: function (power) { | |
return Math.pow(this, power); | |
}, | |
// A simple mapping of Math.abs. | |
abs: function () { | |
return Math.abs(this); | |
}, | |
// We map Math.floor, Math.ceil and Math.round to Number.prototype and add the | |
// ability to define a precision. These are all based on functions written by | |
// Lea Verou. | |
// http://lea.verou.me/2009/02/extend-mathround-mathceil-and-mathfloor-to-allow-precision/ | |
floor: function (precision) { | |
var p = absNumber(precision) || 0, | |
coefficient = (10).pow(p); | |
return Math.floor(this * coefficient) / coefficient; | |
}, | |
ceil: function (precision) { | |
var p = absNumber(precision) || 0, | |
coefficient = (10).pow(p); | |
return Math.ceil(this * coefficient) / coefficient; | |
}, | |
round: function (precision) { | |
var p = absNumber(precision) || 0, | |
coefficient = (10).pow(p); | |
return Math.round(this * coefficient) / coefficient; | |
}, | |
// http://es5.github.com/#sign | |
sign: function () { | |
var number = +this; | |
if (!isNaN(number)) { | |
number = number < 0 ? -1 : 1; | |
} | |
return number; | |
}, | |
// http://es5.github.com/#x9.4 | |
toInt: function () { | |
var number = +this, | |
ret = 0; | |
if (!isNaN(number)) { | |
if (number === 0 || !isFinite(number)) { | |
ret = number; | |
} else { | |
ret = posInt(number); | |
} | |
} | |
return ret; | |
}, | |
// http://es5.github.com/#x9.5 | |
toInt32: function () { | |
var number = +this, | |
ret = 0, | |
two = 2, | |
twoPow32 = two.pow(32); | |
if (!isNaN(number) && isFinite(number)) { | |
ret = posInt(number) % twoPow32; | |
if (ret >= two.pow(31)) { | |
ret -= twoPow32; | |
} | |
} | |
return ret; | |
}, | |
// http://es5.github.com/#x9.6 | |
toUint32: function () { | |
var number = +this, | |
ret = 0; | |
if (!isNaN(number) && isFinite(number)) { | |
ret = posInt(number) % (2).pow(32); | |
} | |
return ret; | |
}, | |
// http://sk80.co.uk/2012/04/number-prototype-times/ | |
times: function (func, thisArg) { | |
var i = 0, | |
t = posInt(this).abs(); | |
if (Object.prototype.toString.call(func) !== '[object Function]') { | |
throw new TypeError(func + ' is not a function'); | |
} | |
while (i < t) { | |
func.call(thisArg, i); | |
i += 1; | |
} | |
return t; | |
} | |
}; | |
}())); | |
Object.update(Array.prototype, (function () { | |
'use strict'; | |
var undef, | |
toString = Object.prototype.toString, | |
isStringArray = 'a'[0] === 'a'; | |
// Converts an object into its primative type, throws errors if it's given null | |
// or undefined. | |
// http://es5.github.com/#x9.9 | |
function toObject(o) { | |
if (o === undef || o === null) { | |
throw new TypeError('can\'t convert null or undefined to object'); | |
} | |
if (!isStringArray && toString.call(o) === '[object String]') { | |
o = o.split(''); | |
} | |
return Object(o); | |
} | |
return { | |
remove: function (entry) { | |
var array = toObject(this), | |
index = array.indexOf(entry); | |
if (index > -1) { | |
array.splice(index, 1); | |
} | |
return array; | |
}, | |
insert: function (first, array, second) { | |
var keyArray = toObject(this), | |
boundArray = toObject(array), | |
index = keyArray.push(first) - 1; | |
boundArray[index] = second; | |
return keyArray; | |
}, | |
// If only "delete" weren't a key word. | |
uninsert: function (entry, array) { | |
var keyArray = toObject(this), | |
boundArray = toObject(array), | |
index = keyArray.indexOf(entry); | |
if (index > -1) { | |
keyArray.splice(index, 1); | |
boundArray.splice(index, 1); | |
} | |
return keyArray; | |
} | |
}; | |
}())); | |
Object.update(Function.prototype, (function () { | |
'use strict'; | |
// These two Arrays are bound, the indices should match. As a function is pushed | |
// into the functions array, an Array containing true or false and the delayed | |
// function is put into the timers array at the same index. | |
var functions = [], | |
timers = []; | |
function checkFunction(func) { | |
if (Object.prototype.toString.call(func) !== '[object Function]') { | |
throw new TypeError(func + ' is not a function'); | |
} | |
} | |
return { | |
delay: function (milliseconds) { | |
checkFunction(this); | |
functions | |
.insert(this, timers, [true, setTimeout(this, milliseconds)]); | |
return this; | |
}, | |
repeat: function (milliseconds) { | |
checkFunction(this); | |
functions | |
.insert(this, timers, [false, setInterval(this, milliseconds)]); | |
return this; | |
}, | |
stop: function () { | |
var index = functions.indexOf(this), | |
timer; | |
checkFunction(this); | |
if (index > -1) { | |
timer = timers[index]; | |
if (timer[0]) { | |
clearTimeout(timer[1]); | |
} else { | |
clearInterval(timer[1]); | |
} | |
functions.uninsert(this, timers); | |
} | |
return this; | |
} | |
}; | |
}())); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment