我想了解 jQuery 插件的语法

JQuery 站点列出了 jQuery 的基本插件语法如下:

(function( $ ){
$.fn.myPlugin = function() {
// there's no need to do $(this) because
// "this" is already a jquery object


// $(this) would be the same as $($('#element'));


this.fadeIn('normal', function(){
// the this keyword is a DOM element
});
};
})( jQuery );

我只是想从 Javascript 的角度来理解这里发生了什么,因为它看起来不像是遵循我以前见过的任何语法。这是我的问题清单:

  1. 如果将 function ($) ... 替换为变量,比如“ the _ function”,语法如下:

     (the_function)( jQuery );
    

    “(jQuery) ;”在做什么?_ 函数周围的括号真的有必要吗?他们为什么在那里?还有其他类似的代码吗?

  2. 它以函数($)开始。所以它创建了一个函数,据我所知永远不会运行,参数是 $,已经定义好了?发生什么事了?

谢谢你的帮助!

6727 次浏览

(function( $ ){


})( jQuery );

That is self-executing anonymous function that uses $ in argument so that you can use it ($) instead of jQuery inside that function and without the fear of conflicting with other libraries because in other libraries too $ has special meaning. That pattern is especially useful when writing jQuery plugins.

You can write any character there instead of $ too:

(function(j){
// can do something like
j.fn.function_name = function(x){};


})(jQuery);

Here j will automatically catch up jQuery specified at the end (jQuery). Or you can leave out the argument completely but then you will have to use jQuery keyword all around instead of $ with no fear of collision still. So $ is wrapped in the argument for short-hand so that you can write $ instead of jQuery all around inside that function.

If you even look at the source code of jQuery, you will see that everything is wrapped in between:

(function( window, undefined ) {
// jQuery code
})(window);

That is as can be seen also a self-executing anonymous function with arguments. A window (and undefined) argument is created and is mapped with global window object at the bottom (window). This is popular pattern these days and has little speed gain because here window is will be looked into from the argument rather than global window object which is mapped below.


The $.fn is jQuery's object where you create your new function (which is also an object) or the plugin itself so that jQuery wraps your plugin in its $.fn object and make it available.


Interestingly, I had answered similar question here:

JavaScript / jQuery closure function syntax

You can also check out this article to know more about self-executing functions that I had written:

Javascript Self-executing Functions

The basic plugin syntax allows you to use $ to refer to jQuery in the body of your plugin, regardless of the identify of $ at the time the plugin is loaded. This prevents naming conflicts with other libraries, most notably Prototype.

The syntax defines a function that accepts a parameter known as $ so you can refer to it as $ in the function body, and then immediately invokes that function, putting jQuery in as the argument.

This also helps not pollute the global namespace (so declaring var myvar = 123; in your plugin body won't suddenly define window.myvar), but the main ostensible purpose is to allow you to use $ where $ may have since been redefined.

The jQuery at the end passes itself (jQuery) over to the function, so that you can use the $ symbol within your plugin. You ccould also do

(function(foo){


foo.fn.myPlugin = function() {




this.fadeIn('normal', function(){




});


};
})( jQuery );

You're dealing with a self-invoking anonymous function there. It's like "best practice" to wrap a jQuery plugin within such a function to make sure, that the $ sign is bound to the jQuery object.

Example:

(function(foo) {
alert(foo);
}('BAR'));

This would alert BAR when put into a <script> block. The parameter BAR is passed to the function which calls itself.

The same principle is happening in your code, the jQuery object is passed to the function, so $ will refer to the jQuery object for sure.

function(x){
x...
}

is just a function without a name, that takes one argument, "x", and does things with x.

Instead of 'x', which is a common variable name, you can use $, which is a less common variable name, but still legal.

function($){
$...
}

I'll put it in parentheses to make sure it parses as an expression:

(function($){
$....
})

To call a function, you put () after it with a list of arguments. For example, if we wanted to call this function passing in 3 for the value of $ we would do this:

(function($){
$...
})(3);

Just for kicks, let's call this function and pass in jQuery as a variable:

(function($){
$....
})(jQuery);

This creates a new function that takes one argument and then calls that function, passing in jQuery as the value.

WHY?

  • Because writing jQuery every time you want to do something with jQuery is tedious.

WHY NOT JUST WRITE $ = jQuery?

  • Because someone else might have defined $ to mean something else. This guarantees that any other meanings of $ are shadowed by this one.

To find a clear explanation of this and other modern javascript tricks and common practices, I recommend reading Javascript Garden.

http://bonsaiden.github.com/JavaScript-Garden/

It's especially useful, because many of these patterns are widely used in many libraries but not really explained.

The other answers here are great, but there is one important point that hasn't been addressed. You say:

So it's creating a function, that as far as I can tell will never be run, with the parameter of $, which is already defined?

There is no guarantee that the global variable $ is available. By default, jQuery creates two variables in the global scope: $ and jQuery (where the two are aliases for the same object). However, jQuery can also be run in noConflict mode:

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
jQuery.noConflict();
</script>

When you call jQuery.noConflict(), the global variable $ is set back to whatever it was before the jQuery library was included. This allows jQuery to be used with other Javascript libraries that also use $ as a global variable.

If you wrote a plugin that relied on $ being an alias for jQuery, then your plugin would not work for users running in noConflict mode.

As others have already explained, the code you posted creates an anonymous function that is called immediately. The global variable jQuery is then passed in to this anonymous function, which is safely aliased as the local variable $ within the function.