class Function
Description
Extensions to the built-in Function object.
Instance methods
-
argumentNames #
Function#argumentNames() ⇒ ArrayReads the argument names as stated in the function definition and returns the values as an array of strings (or an empty array if the function is defined without parameters).
Examples
function fn(foo, bar) { return foo + bar; } fn.argumentNames(); //-> ['foo', 'bar'] Prototype.emptyFunction.argumentNames(); //-> [] -
bind #
Function#bind(context[, args...]) ⇒ Function-
context(Object) – The object to bind to. -
args(?) – Optional additional arguments to curry for the function.
Binds this function to the given
contextby wrapping it in another function and returning the wrapper. Whenever the resulting "bound" function is called, it will call the original ensuring thatthisis set tocontext. Also optionally curries arguments for the function.Examples
A typical use of
Function#bindis to ensure that a callback (event handler, etc.) that is an object method gets called with the correct object as its context (thisvalue):var AlertOnClick = Class.create({ initialize: function(msg) { this.msg = msg; }, handleClick: function(event) { event.stop(); alert(this.msg); } }); var myalert = new AlertOnClick("Clicked!"); $('foo').observe('click', myalert.handleClick); // <= WRONG // -> If 'foo' is clicked, the alert will be blank; "this" is wrong $('bar').observe('click', myalert.handleClick.bind(myalert)); // <= RIGHT // -> If 'bar' is clicked, the alert will be "Clicked!"bindcan also curry (burn in) arguments for the function if you provide them after thecontextargument:var Averager = Class.create({ initialize: function() { this.count = 0; this.total = 0; }, add: function(addend) { ++this.count; this.total += addend; }, getAverage: function() { return this.count == 0 ? NaN : this.total / this.count; } }); var a = new Averager(); var b = new Averager(); var aAdd5 = a.add.bind(a, 5); // Bind to a, curry 5 var aAdd10 = a.add.bind(a, 10); // Bind to a, curry 10 var bAdd20 = b.add.bind(b, 20); // Bind to b, curry 20 aAdd5(); aAdd10(); bAdd20(); bAdd20(); alert(a.getAverage()); // -> Alerts "7.5" (average of [5, 10]) alert(b.getAverage()); // -> Alerts "20" (average of [20, 20])(To curry without binding, see
Function#curry.) -
-
bindAsEventListener #
Function#bindAsEventListener(context[, args...]) ⇒ Function-
context(Object) – The object to bind to. -
args(?) – Optional arguments to curry after the event argument.
An event-specific variant of
Function#bindwhich ensures the function will recieve the current event object as the first argument when executing.It is not necessary to use
bindAsEventListenerfor all bound event handlers;Function#bindworks well for the vast majority of cases.bindAsEventListeneris only needed when:- Using old-style DOM0 handlers rather than handlers hooked up via
Event.observe, becausebindAsEventListenergets the event object from the right place (even on MSIE). (If you're usingEvent.observe, that's already handled.) - You want to bind an event handler and curry additional arguments but have those arguments appear after, rather than before, the event object. This mostly happens if the number of arguments will vary, and so you want to know the event object is the first argument.
Example
var ContentUpdater = Class.create({ initialize: function(initialData) { this.data = Object.extend({}, initialData); }, // On an event, update the content in the elements whose // IDs are passed as arguments from our data updateTheseHandler: function(event) { var argIndex, id, element; event.stop(); for (argIndex = 1; argIndex < arguments.length; ++argIndex) { id = arguments[argIndex]; element = $(id); if (element) { element.update(String(this.data[id]).escapeHTML()); } } } }); var cu = new ContentUpdater({ dispName: 'Joe Bloggs', dispTitle: 'Manager <provisional>', dispAge: 47 }); // Using bindAsEventListener because of the variable arg lists: $('btnUpdateName').observe('click', cu.updateTheseHandler.bindAsEventListener(cu, 'dispName') ); $('btnUpdateAll').observe('click', cu.updateTheseHandler.bindAsEventListener(cu, 'dispName', 'dispTitle', 'dispAge') ); -
-
curry #
Function#curry(args...) ⇒ Function-
args(?) – The arguments to curry.
Curries (burns in) arguments to a function, returning a new function that when called with call the original passing in the curried arguments (along with any new ones):
function showArguments() { alert($A(arguments).join(', ')); } showArguments(1, 2,, 3); // -> alerts "1, 2, 3" var f = showArguments.curry(1, 2, 3); f('a', 'b'); // -> alerts "1, 2, 3, a, b"Function#curryworks just likeFunction#bindwithout the initial context argument. Usebindif you need to curry arguments and set context at the same time.The name "curry" comes from mathematics.
-
-
defer #
Function#defer(args...) ⇒ Number-
args(?) – Optional arguments to pass into the function.
Schedules the function to run as soon as the interpreter is idle.
A "deferred" function will not run immediately; rather, it will run as soon as the interpreter's call stack is empty.
Behaves much like
window.setTimeoutwith a delay set to0. Returns an ID that can be used to clear the timeout withwindow.clearTimeoutbefore it runs.Example
function showMsg(msg) { alert(msg); } showMsg("One"); showMsg.defer("Two"); showMsg("Three"); // Alerts "One", then "Three", then (after a brief pause) "Two" // Note that "Three" happens before "Two" -
-
delay #
Function#delay(timeout[, args...]) ⇒ Number-
timeout(Number) – The time, in seconds, to wait before calling the function. -
args(?) – Optional arguments to pass to the function when calling it.
Schedules the function to run after the specified amount of time, passing any arguments given.
Behaves much like
window.setTimeout, but the timeout is in seconds rather than milliseconds. Returns an integer ID that can be used to clear the timeout withwindow.clearTimeoutbefore it runs.To schedule a function to run as soon as the interpreter is idle, use
Function#defer.Example
function showMsg(msg) { alert(msg); } showMsg.delay(0.1, "Hi there!"); // -> Waits a 10th of a second, then alerts "Hi there!" -
-
methodize #
Function#methodize() ⇒ FunctionWraps the function inside another function that, when called, pushes
thisto the original function as the first argument (with any further arguments following it).The
methodizemethod transforms the original function that has an explicit first argument to a function that passesthis(the current context) as an implicit first argument at call time. It is useful when we want to transform a function that takes an object to a method of that object or its prototype, shortening its signature by one argument.Example
// A function that sets a name on a target object function setName(target, name) { target.name = name; } // Use it obj = {}; setName(obj, 'Fred'); obj.name; // -> "Fred" // Make it a method of the object obj.setName = setName.methodize(); // Use the method instead obj.setName('Barney'); obj.name; // -> "Barney"The example above is quite simplistic. It's more useful to copy methodized functions to object prototypes so that new methods are immediately shared among instances. In the Prototype library,
methodizeis used in various places such as the DOM module, so that (for instance) you can hide an element either by calling the static version ofElement.hideand passing in an element reference or ID, like so:Element.hide('myElement');...or if you already have an element reference, just calling the methodized form instead:
myElement.hide(); -
wrap #
Function#wrap(wrapper) ⇒ Function-
wrapper(Function) – The function to use as a wrapper.
Returns a function "wrapped" around the original function.
Function#wrapdistills the essence of aspect-oriented programming into a single method, letting you easily build on existing functions by specifying before and after behavior, transforming the return value, or even preventing the original function from being called.The wraper function is called with this signature:
function wrapper(callOriginal[, args...])...where
callOriginalis a function that can be used to call the original (wrapped) function (or not, as appropriate). (callOriginalis not a direct reference to the original function, there's a layer of indirection in-between that sets up the proper context [thisvalue] for it.)Example
// Wrap String#capitalize so it accepts an additional argument String.prototype.capitalize = String.prototype.capitalize.wrap( function(callOriginal, eachWord) { if (eachWord && this.include(" ")) { // capitalize each word in the string return this.split(" ").invoke("capitalize").join(" "); } else { // proceed using the original function return callOriginal(); } }); "hello world".capitalize(); // -> "Hello world" (only the 'H' is capitalized) "hello world".capitalize(true); // -> "Hello World" (both 'H' and 'W' are capitalized) -