在包装 jQuery 插件的匿名函数中使用“窗口"、“文档"和“未定义"作为参数

老实说,我不知道如何缩短标题.

我通过研究 SlidesJS 插件的源代码学习了如何编写 jQuery 插件.当我遇到新事物时,我只是问了我的好朋友 Google,而且大多数时候都得到了满意的答案.不过老实说,我从来没有努力过.我所知道的是 $ (可能)是一个简写的 jQuery 对象构造函数,并且 $()jQuery() 是相同的东西提供包含 jQuery.

不过,最近,我尝试了解 jQuery 背后的科学以及如何编写 good jQuery 插件.我遇到了一篇非常好的 文章,其中作者列出了几个用于创建 jQuery 插件的 模板.因为其余的太复杂了,我无法理解,所以我喜欢第一个:轻量级的开始.现在,这里是上述模板的代码.

<代码>/*!* jQuery轻量级插件样板* 原作者:@ajpiano* 进一步的变化,评论:@addyosmani* 在 MIT 许可下获得许可*///函数调用前的分号是安全的//网络连接脚本和/或其他插件//没有正确关闭.;(函数 ($, 窗口, 文档, 未定义) {//这里使用 undefined 作为 undefined 全局//ECMAScript 3 中的变量并且是可变的(即它可以//被其他人更改).undefined 不是真的//被传入所以我们可以确保它的值是//真正未定义.在 ES5 中,undefined 不能再//修改的.//窗口和文档作为本地传递//变量而不是全局变量,因为这个(稍微)//加快解析过程,可以更多//有效地缩小(尤其是当两者都是//在你的插件中经常引用).//创建一次默认值var pluginName = 'defaultPluginName',默认值 = {属性名称:值"};//实际的插件构造函数功能插件(元素,选项){this.element = 元素;//jQuery 有一个扩展方法,可以合并//两个或多个对象的内容,存储//结果是第一个对象.第一个对象//通常是空的,因为我们不想改变//未来插件实例的默认选项this.options = $.extend( {}, 默认值, 选项) ;this._defaults = 默认值;this._name = pluginName;this.init();}Plugin.prototype.init = function () {//这里放置初始化逻辑//你已经可以访问 DOM 元素并且//通过实例的选项,例如这个元素//和 this.options};//一个非常轻量级的围绕构造函数的插件包装器,//防止多次实例化$.fn[pluginName] = 功能(选项){返回 this.each(function () {if (!$.data(this, 'plugin_' + pluginName)) {$.data(this, 'plugin_' + pluginName,新插件(这个,选项));}});}})( jQuery, 窗口, 文档);

我已将评论包括在内,以便在我的问题中引用它们.

我有一个粗略的想法,为什么 windowdocument 被包含在包装插件的匿名函数的参数中(我不知道是什么否则调用它) 因为它在评论中给出它有点缩短执行时间.但这是如何工作的?包装插件的上述匿名函数的任何参数都会传递到哪里?这些在插件中是如何解决的?

通常,我会这样做 $(window).resize(function(){}) 但在这种情况下不起作用.如果我在插件函数中执行 console.log(window),它会显示未定义".

这让我想到另一个问题:undefined 是什么?不是分配给未在范围内定义的对象的数据类型吗?它如何作为参数传递?论点不是必须是对象吗?评论中写了几行关于此的内容,但我一个字都看不懂:<所以我们可以确保它的值是真正未定义的> whaaa?

总结一下:

  • function($)究竟是什么意思?
  • 为什么要在 function($) 的参数中包含 windowdocumentundefined?李>
  • 如果这样做,如何访问实际的 windowdocument 对象?
  • 未定义什么,为什么?
<小时>

请对我放轻松.我从来没有为了编写应用程序的明确目的而将编程语言作为一门学科.我学习了基本的 C 语言,用于为微型核心微控制器编写面向硬件的低级例程,仅此而已.我确实广泛地学习了 C++ 和一点点 Java.只是为了让您知道会发生什么.

解决方案

当你写这样的函数时:

(function (foo, bar) {返回 foo.getElementById(bar);})(文档,我的元素")

然后立即使用参数 document"myElement" 为参数 foobar 调用该函数.因此,在函数内部,foo.getElementById(bar)等价于document.getElementById("myElement").

同样,在您的插件示例中,您会立即使用参数 jQuery, document, window 调用该函数.

<块引用>

function($)究竟是什么意思?

$ 仅表示对传递给包装函数的 jQuery 对象的引用.稍后,当使用 (jQuery, window, document) 调用匿名函数时,函数内部的 $ 引用引用了 jQuery 对象.这样做的原因有很多,其中最重要的是 $ 可以更快地键入.它还允许用户将包装器中的插件应用到 jQuery 的 特定实例,可能由 jQuery.noConflict() 生成.p><块引用>

我为什么要包含 windowdocumentundefined 作为 function($) 的参数?p>

您不需要包含这些.原作者的推理是分配函数局部变量来引用这些将缩短解析这些变量所需的时间.我断言节省的费用微不足道;除非我使用 大量 对 window 和/或 document 的引用,否则我个人不会打扰.

至于 undefined,原作者包含此内容的目的是确保有人没有更改 EcmaScript 4 中的 undefined 全局变量(实际上是 ECMAScript 3-- 版本 4 从未成功)或更早版本.同样,我无法想象会出现这个问题.如果你真的担心这可能是一个问题,只需在你的函数中包含这样的内容:

if(typeof undefined !== "undefined") {未定义=无效0;}

<块引用>

如果我这样做,我如何访问实际的 windowdocument 对象?

您所要做的就是确保匿名函数末尾的函数调用传入实际的(jQuery、窗口、文档)参数.或者,不要在函数签名中包含 windowdocument 参数.无论哪种方式,您都将引用 实际 对象,而不管间接级别如何.

<块引用>

未定义什么,为什么?

undefined 是未定义"类型的全局变量.尚未初始化的字段与未定义完全相等 (===).它允许程序员区分一个故意为空的值和一个简单的未初始化的值.在 ECMAScript 5 及更高版本中,undefined 是只读的.在此之前,其他代码可能会修改 undefined 的值.您可以总是使用表达式 void 0... 获取真值 undefined,如 myUndefinedVar = void 0;.

Honestly, I didn't know how to make the title shorter.

I learnt how to write a jQuery plugin by studying the source of SlidesJS plugin. When I encountered something new, I just asked my good friend Google and most of the times, got a satisfactory answer. Honestly though, I never made much effort. All I know is that $ is (probably) a shorthand jQuery object constructor and that $() and jQuery() are the same thing provided jQuery is included.

Recently, though, I tried to understand the science behind jQuery and how to write a good jQuery plugin. I came across a very good article in which the author listed several templates for creating a jQuery plugin. Since the rest were too complex for me to understand, I liked the first one: A Lightweight Start. Now, here is the code for the said template.

/*!
 * jQuery lightweight plugin boilerplate
 * Original author: @ajpiano
 * Further changes, comments: @addyosmani
 * Licensed under the MIT license
 */


// the semi-colon before the function invocation is a safety 
// net against concatenated scripts and/or other plugins 
// that are not closed properly.
;(function ( $, window, document, undefined ) {

    // undefined is used here as the undefined global 
    // variable in ECMAScript 3 and is mutable (i.e. it can 
    // be changed by someone else). undefined isn't really 
    // being passed in so we can ensure that its value is 
    // truly undefined. In ES5, undefined can no longer be 
    // modified.

    // window and document are passed through as local 
    // variables rather than as globals, because this (slightly) 
    // quickens the resolution process and can be more 
    // efficiently minified (especially when both are 
    // regularly referenced in your plugin).

    // Create the defaults once
    var pluginName = 'defaultPluginName',
        defaults = {
            propertyName: "value"
        };

    // The actual plugin constructor
    function Plugin( element, options ) {
        this.element = element;

        // jQuery has an extend method that merges the 
        // contents of two or more objects, storing the 
        // result in the first object. The first object 
        // is generally empty because we don't want to alter 
        // the default options for future instances of the plugin
        this.options = $.extend( {}, defaults, options) ;

        this._defaults = defaults;
        this._name = pluginName;

        this.init();
    }

    Plugin.prototype.init = function () {
        // Place initialization logic here
        // You already have access to the DOM element and
        // the options via the instance, e.g. this.element 
        // and this.options
    };

    // A really lightweight plugin wrapper around the constructor, 
    // preventing against multiple instantiations
    $.fn[pluginName] = function ( options ) {
        return this.each(function () {
            if (!$.data(this, 'plugin_' + pluginName)) {
                $.data(this, 'plugin_' + pluginName, 
                new Plugin( this, options ));
            }
        });
    }

})( jQuery, window, document );

I have included the comments so as to refer to them in my questions.

I have a crude idea why window and document have been included in the argument of the anonymous function that wraps the plugin (I don't know what else to call it) because it is given in the comments that it sorta kinda shortens the execution time. But how does that work? Any argument of the said anonymous function wrapping the plugin gets passed on to where? And how are these addressed in the plugin?

Normally, I would do $(window).resize(function(){}) but that doesn't work in this case. If I do console.log(window) inside the Plugin function, it says 'undefined'.

Which brings me to the other question which is: what is undefined? Isn't it a data type that is assigned to an object that isn't defined in the scope? How can it be passed as an argument? Don't the arguments have to be objects? There are a few lines written about this in the comments, but I don't understand a word of it: <so we can ensure that its value is truly undefined> whaaa?

To sum up:

  • What indeed is meant by function($)?
  • Why should I include window, document and undefined as arguments of function($)?
  • If I do it, how do I access the actual window and document objects?
  • undefined what, and why?

Please go easy on me. I never studied programming language as a subject for the express purpose of writing applications. I studied basic C for writing hardware oriented low-level routines for tiny core microcontrollers and that's just about it. I did learn C++ extensively and a bit of Java on my own. Just so you'd know what to expect.

解决方案

When you write a function like:

(function (foo, bar) {
    return foo.getElementById(bar);
})(document, "myElement")

then the function is immediately called with arguments document and "myElement" for parameters foo and bar. Therefore, inside the function, foo.getElementById(bar) is equivalent to document.getElementById("myElement").

Similarly, in your plugin example, you are immediately calling the function with the arguments jQuery, document, window.

What indeed is meant by function($)?

The $ simply represents a reference to a jQuery object that is passed in to the wrapper function. Later, when the anonymous function is called with (jQuery, window, document), the $ reference inside the function references the jQuery object. This is done for a number of reasons, not least of which is that $ is quicker to type. It also allows the user to apply your plugin in wrapper to a particular instance of jQuery, produced perhaps by jQuery.noConflict().

Why should I include window, document and undefined as arguments of function($)?

You don't need to include these. The original author's reasoning is that assigning function-local variables to reference these will shorten the time it takes to resolve these variables. I assert that the savings are negligible; I personally wouldn't bother unless I used a lot of references to window and/or document.

As for undefined, the original author's purpose in including this is to ensure that someone hasn't altered the undefined global variable in EcmaScript 4 (edit: actually ECMAScript 3 -- version 4 never made it) or earlier. Again, I can't envision this problem cropping up. If you're truly worried that this could be a problem, just include something like this in your function:

if(typeof undefined !== "undefined") {
    undefined = void 0;
}

If I do it, how do I access the actual window and document objects?

All you have to do is make sure that the function call at the end of your anonymous function passes in the actual (jQuery, window, document) parameters. Or, don't include the window and document arguments in your function signature. Either way, you will be referring to the actual objects, regardless of the level of indirection.

undefined what, and why?

undefined is a global variable of type "undefined". Fields that have not been initialized are exactly equal (===) to undefined. It allows the programmer to differentiate between a deliberately null value and a simple uninitialized one. In ECMAScript 5 and later, undefined is read only. Prior to that, it is possible that other code could modify the value of undefined. You can always get the true value undefined with the expression void 0... as in myUndefinedVar = void 0;.

相关文章