web-dev-qa-db-ja.com

jQueryプラグインをラップする無名関数の引数として「window」、「document」、「undefined」を使用する

正直なところ、タイトルを短くする方法がわかりませんでした。

SlidesJS プラグインのソースを調べて、jQueryプラグインの書き方を学びました。何か新しいことに遭遇したとき、私はちょうど私の親友Googleに尋ねました、そしてほとんどの場合、満足のいく答えを得ました。正直なところ、私はあまり努力しませんでした。私が知っているのは、_$_は(おそらく)省略形のjQueryオブジェクトコンストラクターであり、$()jQuery()はjQueryが含まれていれば同じものであるということだけです。

しかし最近、私はjQueryの背後にある科学と、goodjQueryプラグインの書き方を理解しようとしました。私は非常に良い 記事 に出くわしました。そこでは著者がjQueryプラグインを作成するためのいくつかのテンプレートをリストしました。残りは私が理解するには複雑すぎたので、私は最初のものが好きでした:軽量スタート。さて、これが前述のテンプレートのコードです。

_/*!
 * 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 );
_

質問で参照できるようにコメントを含めました。

プラグインをラップする無名関数の引数にwindowdocumentが含まれている理由は大まかな考えです(他に何を呼び出すべきかわかりません) it)コメントにあるので、実行時間が少し短くなります。しかし、それはどのように機能しますか?プラグインをラップする前述の無名関数の引数はどこに渡されますか?そして、これらはプラグインでどのように対処されますか?

通常は$(window).resize(function(){})を実行しますが、この場合は機能しません。プラグイン関数内でconsole.log(window)を実行すると、「undefined」と表示されます。

undefinedとは何ですか? オブジェクトに割り当てられているのはデータ型ではありませんか?スコープで定義されていませんか?どうすれば引数として渡すことができますか?引数はオブジェクトである必要はありませんか?コメントにこれについて書かれた数行がありますが、私はそれの言葉を理解していません:<だから、その値が本当に未定義であることを確認できます> whaaa?

総括する:

  • function($)とはどういう意味ですか?
  • function($)の引数としてwindowdocument、およびundefinedを含める必要があるのはなぜですか?
  • それを行う場合、実際のwindowおよびdocumentオブジェクトにアクセスするにはどうすればよいですか?
  • undefined何、そしてなぜ?

気楽に行ってください。私は、アプリケーションを書くという明確な目的のために、プログラミング言語を主題として勉強したことはありません。私は、小さなコアマイクロコントローラー用のハードウェア指向の低レベルルーチンを作成するための基本的なCを研究しましたが、それだけです。私はC++を広範囲に学び、少しJava自分で学びました。あなたが何を期待するかを知っているように。

25
Zia Ur Rehman

次のような関数を書くとき:

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

次に、関数は、パラメーターdocumentおよびfooに対して引数barおよび_"myElement"_を使用してすぐに呼び出されます。したがって、関数内では、foo.getElementById(bar)document.getElementById("myElement")と同等です。

同様に、プラグインの例では、引数_jQuery, document, window_を使用して関数をすぐに呼び出しています。

function($)とはどういう意味ですか?

_$_は、ラッパー関数に渡されるjQueryオブジェクトへの参照を表すだけです。後で、匿名関数が_(jQuery, window, document)_で呼び出されると、関数内の_$_参照はjQueryオブジェクトを参照します。これはいくつかの理由で行われますが、特に_$_の方が入力が速いという理由があります。また、ユーザーはプラグインをラッパーでjQueryの-​​特定のインスタンスに適用できます。これはおそらくjQuery.noConflict()によって生成されます。

function($)の引数としてwindowdocument、およびundefinedを含める必要があるのはなぜですか?

これらを含める必要はありません必要。元の著者の推論は、これらを参照するために関数ローカル変数を割り当てると、これらの変数を解決するのにかかる時間が短縮されるというものです。私は、節約はごくわずかであると断言します。 windowおよび/またはdocumentへの参照をたくさん使用しない限り、個人的には気にしません。

undefinedに関しては、これを含める元の作成者の目的は、誰かがEcmaScript4のundefinedグローバル変数を変更していないことを確認することです(編集:実際にはECMAScript3-バージョン4は変更していません)またはそれ以前。繰り返しになりますが、この問題が発生することは想像できません。これが問題になる可能性があることを本当に心配している場合は、関数に次のようなものを含めてください。

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

それを行う場合、実際のwindowおよびdocumentオブジェクトにアクセスするにはどうすればよいですか?

あなたがしなければならないのは、無名関数の最後の関数呼び出しが実際の(jQuery、window、document)パラメーターを渡すことを確認することだけです。または、関数のシグネチャにwindow引数とdocument引数を含めないでください。いずれにせよ、間接参照のレベルに関係なく、実際のオブジェクトを参照することになります。

undefined何、そしてなぜ?

undefinedは、タイプ「undefined」のグローバル変数です。初期化されていないフィールドは、未定義とまったく同じ(===)です。これにより、プログラマーは意図的にnull値と単純な初期化されていない値を区別できます。 ECMAScript 5以降では、undefinedは読み取り専用です。それ以前は、他のコードがundefinedの値を変更する可能性があります。 常に _void 0_のように、式_myUndefinedVar = void 0;_...を使用して真の値undefinedを取得できます。

23
bchociej

function($)とはどういう意味ですか?

関数に引数として_$_を渡すと、jQuery省略形オブジェクトを使用できるようになります。これは、明確に識別したように、jQueryオブジェクトのエイリアスにすぎません( jQuery.noConflict() )も見てください。

function($)の引数としてwindowdocument、およびundefinedを含める必要があるのはなぜですか?プラグインをラップする無名関数の引数にウィンドウとドキュメントが含まれている理由は大まかな考えです(他に何を呼び出すべきかわかりません)。コメントに記載されているため、実行時間が少し短縮されます。 。しかし、それはどのように機能しますか?プラグインをラップする前述の無名関数の引数はどこに渡されますか?

windowdocumentをローカル変数として渡すと、グローバル変数よりもローカル変数にアクセスする方が簡単で高速なので、実行時間が短縮されますローカル変数がチェーンの最初にあるため 。 2番目の質問にどのような答えがありますか:引数は無名関数scope内で渡されます。これは、とにかく無名関数を作成することの要点です。

これらの引数は、最後の括弧が表示されている関数の最後に渡されます。クロージャ内の変数windowは、最後に渡したため、_global window_を参照します。

undefinedを渡す理由は、undefinedがJavascriptの混乱を招くためです。基本的に、 undefinedグローバルオブジェクト のプロパティです。つまり、は変数、シングルトンです。保護されていません、つまりオーバーライドできます。これは、実際に定義されているundefinedを持つことができることを意味します。

undefinedを渡すことで、グローバルスコープでundefinedをいじったとしても(グローバルスコープを信用しないでください!:))、正しいundefinedを取得できるようになります。 。

また、同じパフォーマンス上の理由がundefinedにも当てはまります。

それを行う場合、実際のウィンドウとドキュメントオブジェクトにアクセスするにはどうすればよいですか?

それらを関数に渡すため、すでにアクセスしています。そのため、それらを操作することができます。

3
Sunyatasattva

パラメータリストに識別子を含めることは、関数本体で変数を宣言することと実質的に同じです。

function bar(foo) {
}

と同等です

function bar(foo) {
  var foo;
}

ただし、もちろん、fooに値を渡したい場合は、最初に実行します。

行う主な理由:

(function($) {
    // use $ here instead of jQuery
}(jQuery));

jQueryがリリースされたとき、Prototype.jsはすでにしばらくの間そのメイン関数の識別子として「$」を使用していたということです。上記のパターンでは、jQueryとprototype.jsを同じページで使用でき、「$」をさまざまなものの識別子として使用できます。

documentwindowを渡すことは、せいぜい、ほとんどメリットのないマイクロ最適化です。予想とは異なる値が割り当てられるのを防ぐことはできません。関数内でwindowdocumentをグローバル識別子としてわざわざ使用しないでください。

パラメータにundefinedを含めて値を渡さないことは、undefinedが実際に未定義であることを保証する賢明な方法ではありません。値が誤って渡された場合に影響を受けます。より安全な方法は次のとおりです。

(function() {
    var undefined;
    ...
}());

これで、特定の関数のスコープ内のundefinedは実際には未定義です。または、割り当てが必要な場合:

(function() {
    var undefined = void 0;
    ...
}());

しかし、それは単なる余分なタイピングです。

0
RobG