1

My understanding is that a function in JavaScript can have states. Some states need to be initialized just once. How do you do that so that calling the function does not re-initialize them?

For example, $() in jQuery is a function, not an object, and yet it seems to have states and act like an object.

I thought about creating an object for this, but what I want is really a facade function, much like the way $() works.

4
  • Define "function with state". function f() {}; f.x = 0; works, but the rest of the question doesn't read like you talk about that. Commented Jan 23, 2011 at 18:22
  • Functions are objects, too, as is pretty much everything in JavaScript. Commented Jan 23, 2011 at 18:23
  • @janmoesen: Except primitive variables (strings, numbers, booleans) and the primitives null and undefined. Commented Jan 23, 2011 at 18:34
  • @janmoesen - ...but not quite everything. Commented Jan 23, 2011 at 18:34

3 Answers 3

7

Functions are objects. They can have properties:

function F() {}
F.key = "value";
alert(F.key) // "value"

You can also use functions as constructors called with new:

function F(val) { this.key = val; }
var instance = new F("value")
alert(instance.key) // "value"

The difference as you can see is that the first version only adds a key memeber to the F function object, while the second one initializes a new key member on every instance created by newF.

When you call a function via new an instance object is automatically created and can be augmented by the this keyword. Every constructor returns this by default.

You can also add public methods to the function's prototype, and they will be available for all the instances. They can change their "state" (as you call it) individually using the this keyword.

function F(val) { this.state = val; } // unique
F.prototype.change = function() { this.state = "stuff"; } 

var inst  = new F("value")
var inst2 = new F("value")

alert(inst.state)  // "value"
alert(inst2.state) // "value"

inst.change();

alert(inst.state)  // "stuff"
alert(inst2.state) // "value"

jQuery

I can even tell you what jQuery is doing behind the scenes, but I don't think you really want to know. :)

var jQuery = function( selector, context ) {
        // The jQuery object is actually just the init constructor 'enhanced'
        return new jQuery.fn.init( selector, context );
    },

// ...

jQuery.fn = jQuery.prototype = {
    init: function( selector, context ) {
       // ...
    },
    // ...
};

// Give the init function the jQuery prototype for later instantiation
jQuery.fn.init.prototype = jQuery.fn;

So basically $(selector) means newjQuery.fn.init(selector), it's just a shortcut for easier typing (and also to prevent the "bug" mentioned in the comments where fogetting new binds this to the global object, instead of the current instance).

Also, the so-called plug-ins added as jQuery.fn.ext are mapped to jQuery.fn.init.prototype as you can see in the last line, it's another shortcut. So when you call $(selector) everything that is added to jQuery.fn will also be on jQuery.fn.init.prototype and so the new instance will have those methods as $(selector).ext(...).

// as you use it today
jQuery.fn.plugin = function ( ... ) { ... }
$(selector).plugin( ... )

// as it would be without shortcuts
jQuery.fn.init.prototype.plugin = function ( ... ) { ... }
(new jQuery.fn.init(selector)).plugin( ... )
Sign up to request clarification or add additional context in comments.

3 Comments

it's worth noting that if you don't use the F function with new, this.key will refer to the global this.
Thank you! Just curious though - why did they make it "var jQuery = function(selector, context)" instead of "function jQuery(selector, context)"?
@Tom Tucker - It would be another long story :) But honestly, I don't thing you need to imitate the design of jQuery. Go with something more simple, and pleasant looking. :)
0

If you want to restrict a function from be called more than once, i suggest you implement the singleton pattern

Comments

-1

JavaScript is fully object oriented, prototype-based language. And by fully I mean everything is an object including arrays, numbers and so-called functions:

var number = 32.1245;
alert(number.toFixed(2)); // 32.12

Basically when you define a function using function keyword you're actually defining a object constructor. Inside object constructor you can define object's public properties using this:

function Car(model) {
   this.model = model;
   this.productionYear = new Date().getFullYear();
}

var car = new Car("Audi A8");
car.productionYear = 2009;

Of course those properties can be objects constructors as well.

5 Comments

The contents of your constructor are useless and misleading.
@Crozin - typeof 32.1245 ? There are primitives in the language that are not objects.
@galambalazs: No, it's not a primitive (JS doesn't have such), it's an object - Number object to be precise.
@Crozin - ECMA-262 5th Edition - " 4.3.2 primitive value - member of one of the types Undefined, Null, Boolean, Number, or String as defined Clause 8. NOTE: A primitive value is a datum that is represented directly at the lowest level of the language implementation. "
@Crozin - btw w3Schools is rather old (and bad) but it's not mistaken when it says "The Number object is an object wrapper for primitive numeric values." - Thus of course typeof Number(32) is object, but typeof 32 is still number, because it's a primitive value.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.