开发者

Creating a jQuery plugin: best practices regarding functions' visibility?

I'm creating a jQuery plugin. So far it's working fine, but I'm having doubt about the way I'm doing things:

jQuery.fn.myMethod = function() {
  return this.each(function(){
    MyScope.doSomething(jQuery(this).attr("id"));
  });
};

var MyScope = {

  // The functions contained in MyScope are extremely linked to the logic 
  // of this plugin and it wouldn't make a lot of sense to extract them

  doSomething: function(id){
    // something
    doSomethingElse(23);
    // some more code
    doSomethingElse(55);
  },

  doSomethingElse: function(someInt){
    // some code 
  }
};

I use MyScope to store all my "private" functions. I don't want the user to be able to go $("p").doSomething(), but I do need to use them.

I could mo开发者_如何学运维ve everything in the myMethod function, but it would create a 100 lines long function and people would hate me for it.

What's the best practices in this situation? Are there any great tutorials out there regarding this?


You can encapsulate your functions to do what you want, like this:

jQuery.fn.myMethod = function() {
  return this.each(function(){
    doSomething(jQuery(this).attr("id"));
  });        
  function doSomething(id){
    //do something
  }
  function doSomethingElse(){
    // some code
  }
};

You can view a quick demo here

"I could move everything in the myMethod function, but it would create a 100 lines long function and people would hate me for it." ....why?

The code has to be defined somewhere, if you don't want it to be externally accessible there are a few ways, but I don't see why anyone would dislike you doing exactly this. It's all about scope and where you want things, as long as you're not declaring it multiple times and exposing only what you want, I don't see any problem.

There are several styles to declaring it, some with the same effect, the option I gave is one of many, but placing things inside myMethod is a perfectly reasonable approach.


To be more complete, here's another alternative:

(function($) { 
    function doSomething(id){
      //do something, e.g:  doSomethingElse('bob');
    }
    function doSomethingElse(str){
      //some code
    }
    $.fn.myMethod = function() {
      return this.each(function(){
        doSomething(jQuery(this).attr("id"));
      });   
    };
})(jQuery);

Or another:

(function($) { 
    var me = {
        doSomething: function(id){
         //do something, e.g:  this.doSomethingElse('bob');
        },
        doSomethingElse: function(str){
          //some code
        }
    };
    $.fn.myMethod = function() {
      return this.each(function(){
        me.doSomething(jQuery(this).attr("id"));
      });   
    };
})(jQuery);

Related articles:

  • JavaScript Module Pattern: In-Depth
  • JavaScript Closures for Dummies


There's nothing wrong with using a large function just to create a new scope. The following keeps doSomething and doSomethingElse private and avoids defining new doSomething and doSomethingElse functions for each invocation of myMethod, which is what would happen if you put doSomething and doSomethingElse inside myMethod's definition.

(function() {
  function doSomething(id) {
    // Something
  }

  function doSomethingElse() {
    // Something else
  }

  jQuery.fn.myMethod = function() {
    return this.each(function(){
      doSomething(this.id);
    });
  };
})();


I would put everything inside the jQuery.fn.myMethod function, to avoid possible namespace collisions, and make for cleaner code. This pattern also allows you to to make private methods which are not accessible from outside the myMethod function.

jQuery.fn.myMethod = function(options) {
  // Set up a "that" object, which can be referenced from anywhere inside this function
  var that = {};

  // If the plugin needs optional arguments, you can define them this way
  if (typeof(options) == 'undefined') options = {};
  that.options.option1 = options.option1 || 'default value 1';
  that.options.option2 = options.option2 || 'default value 2';

  that.init = function() {
    // psuedo-constructor method, called from end of function definition
  }

  that.doSomething = function() {
    // something
  }

  that.doSomethingElse = function() {
    // something else
  } 

  // Call init method once all methods are defined
  that.init();

  // Return the matched elements, to allow method chaining
  return jQuery(this);
}
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜