开发者

How to initialize a JavaScript function

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开发者_StackOverflow-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.


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( ... )


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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜