banger
banger

Reputation: 15

How can I create a private method inside a plugin?

I would like to know if it is possible to create a jQuery private method inside the method like this:

(function($) {
    $.fn.myPublicFunc = function() { 
        $.fn.myPrivateFunc = function() {    
            return this;
        };

        $("a").myPrivateFunc();

        return this;
    };
}(jQuery));

or is there another way to join my normal private functions like:

var myPrivateFunc = function() {
}

into jQuery chain. Sorry for my vocabulary, I hope you will understand my point.

Upvotes: 2

Views: 77

Answers (2)

Ian Clark
Ian Clark

Reputation: 9347

In order for a method to be chain-able, it must necessarily be public, and so not as a method on an object. In JavaScript, scope is set at the function level, and so myPrivateFunction would be visible only to the $.fn.myPublicFunc method.

You can define a function as you normally would, within the scope of the $.fn method, and it'll work just fine:

(function($) {
    $.fn.myPublicFunc = function() { 
        var myPrivateFunction = function(elem) {
            return elem;
        };

        myPrivateFunction($("a"));

        return this;
    };
}(jQuery));

JavaScript functions can have their context overriden, and so your initial goal of having myPrivateFunction take no arguments could work, using either JavaScript's native Function.[call/apply/bind] methods, or using jQuery's $.proxy approach. Here's an example of how that would work with the native Function.call().

var myPrivateFunction = function() {
    return this;
};

myPrivateFunction.call($("a"));

One drawback of this, is that the context in which myPrivateFunction is supposed to be invoked is not clear (without necessary documentation), and so JSHint and other JS linters will complain if your modules are adhering to strict mode rules.

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1074475

There are a couple of places you can create private functions:

  1. One copy for the plugin as a whole

  2. A copy per jQuery object using the plugin

I recommend #1. Here's how you do that:

function($) {
    $.fn.myPublicFunc = function() { 

        myPrivateFunc($("a"));

        return this;
    };

    function myPrivateFunc($set) {
        // Stuff using `$set` here, for instance
        $set.css("color", "green");
    }
}(jQuery));

Note where the private function is created: In the scoping function you wrapped around your plugin's code. Only one copy of the function is created, and then you pass it the jQuery set to work with.

There, $set is the jQuery set (object) that myPrivateFunc should operate on.

If you prefer to use this instead, you use Function#call to call it:

function($) {
    $.fn.myPublicFunc = function() { 

        myPrivateFunc.call($("a"));

        return this;
    };

    function myPrivateFunc() {
        // Stuff using `this` here, for instance
        this.css("color", "green");
    }
}(jQuery));

Note that this is the jQuery set, not a DOM element as it is in event callbacks.

Upvotes: 1

Related Questions