Storing Property Data In Javascript Function Objects
Posted March 10, 2009 at 9:34 AM by Ben Nadel
I was reading up on some jQuery plugin development the other day and I saw something that I had never seen before - someone was storing data as a property of a Javascript function. I have messed around with storing data in the Prototype of a function object, but I've never stored arbitrary data as a property; I didn't even know that one could do such a thing. If you have no idea what I'm talking about, here's a small example:
- <script type="text/javascript">
-
- // Define a simply method that alerts a property
- // of itself.
- function Test(){
- alert( Test.Data );
- }
-
- // Define a property on the method.
- Test.Data = "Method property";
-
-
- // Execute the method.
- Test();
-
- </script>
Notice that we are defining the Test() function and then we are storing a property directly in that function as if the Function object were a standard object (which, in fact, it is). And, when we run this code, it properly alerts:
Method property
There's something really cool about this!
Now, I came across this when looking into jQuery plugin development and the way it was being used there was also very cool; it was being used to store a plugin's default options. It's common in jQuery to be able to pass an options-map into a function that can override a default option set. But, where is the default option set defined? In the example I saw, the default options were being stored as a property of function object itself:
- <script type="text/javascript">
-
- // Define the jQuery plugin.
- jQuery.fn.Test = function( objOptions ){
-
- // Use the passed-in option to override any default
- // option that are provided by the plugin.
- var objSettings = jQuery.extend(
- {},
- jQuery.fn.Test.Default,
- objOptions
- );
-
- // Alert the final data value.
- alert( objSettings.Data );
-
- // Return this for method chaining.
- return( this );
- }
-
- // Define the jQuery method's default properties.
- jQuery.fn.Test.Default = {
- Data: "Default data"
- };
-
-
- // When the document has loaded, run the plugin.
- $(
- function(){
- $( document ).Test( {} );
-
- }
- );
-
- </script>
Here, we define our plugin method, then after it, we define a default options map as a property directly on the function itself. Then, when the plugin is executed, we are extending this default property map with the passed-in property map.
How cool is that! I am not sure how I would use this outside of plugin development; but, for jQuery plugin development, this technique seems quite perfect.
Reader Comments
Hey, that's a really nice tip Ben. I saw it once, but didn't really bother to go after it and see what it was actually doing. Laziness at the extreme :-)
I've also been playing with some plug-in development in jQuery, and this sure will be useful.
The technique is used allow for a wide range of options to be passed into a function, typically as a configuration, without affecting an API's signature/contract. I first saw this in the Ext-JS library and it has been a constant throughout Ext's evolution.
It's also very powerful when combined with Crockford's Module pattern.
You call it laziness - I call it efficiency. ;)
@Marcos,
It's kind of odd to think you can store properties on a variable AND execute it. I guess if you think about parenthesis as operators, it's not so weird... but it's still weird :)
@Claude,
I'm definitely familiar with the idea of passing in an options object to a method for flexibility - jQuery does this on many things and it is certainly something that I've come to appreciate. What I thought was really cool, though, was how the default settings map was being stored as a property of the function itself - I had never seen this before.
Can you point me in the direction of Crockford's Module pattern. This sounds interesting.
You've seen it already in jQuery in the form of namespacing.
YUI Blog: http://yuiblog.com/blog/2007/06/12/module-pattern/
Chris Heilmann: http://www.wait-till-i.com/2007/07/24/show-love-to-the-module-pattern/
Not only can you do that but you can have private, privilaged and public members.
http://javascript.crockford.com/private.html
@Claude,
Thanks, I'll take a look at those links. I am a bit familiar with namespacing in jQuery, but am interested to learn more about how this is used.
@George,
I think the idea of private variables and methods is interesting, but I have not seen a real use for it just yet.
Another use of setting properties on a function is memoization. If you have a function that takes a while to run, after the first time it's called you can store or 'memoize' the result. Here's a crude example:
function fn() {
if (!fn.memo) fn.memo = expensiveOperation();
return fn.memo;
}
If you don't like having hardcoded references to the name of your function inside that function's definition, you can also use arguments.callee to get a reference:
function fn() {
var me = arguments.callee;
if (!me.memo) me.memo = expensiveOperation();
return me.memo;
}
This also allows you to get/set properties on anonymous functions!
I highly recommend Googling "javascript memoization" for a slew of terrific articles. Functional programming is an elegant paradigm, and it's making a comeback thanks to JavaScript.
@David,
Oh that is really cool :) I also totally forgot that you can get the callee from the argument collection. What's lame is that:
console.log( arguments )
... in FireBug does NOT output the callee property. No wonder I forgot about it (hmmph!).
Very cool tip though, thanks.



