8

jQuery は、そのコンストラクターが引数を受け取る関数として機能する一方で、そのコンストラクターが引数を受け取る関数としても機能することをどのように許可しますか?

私はJavaScriptに少し慣れていないので、これが初心者の質問である場合はすみません(ソースを見ましたが、分析するのは難しいです).

とにかく、例として$(document).ready(<args>);コンストラクタ$()とプロトタイプの両方がready()関数として機能します。どのように?私がこれを試してみると:

var $ = function( selector ) {
    if(selector == document) {
        return document;
    }
};

$.prototype = {
    constructor: $,
    ready: function( args ) {
        if( isDomReady ) {
            args.apply( document );
        } else {
            window.onload = args;
        }
    }
};

var isDomReady = ( document.addEventListener || document.readyState == ("complete"|"loaded"|true|4) || document.onreadystatechange() ) ? true : false;

$(document).ready(function() { alert("Wibbles!") });

エラーが発生するUncaught TypeError: Object[object global] has no method 'ready'

4

2 に答える 2

8

これにはかなり興味をそそられました。あなたはすでに回答を受け入れていますが、それが有用であることが判明した場合に備えて、私の回答を投稿させてください. ここに作成されたフィドルがあります

jQuery = function( selector, context ) {
    // The jQuery object is actually just the init constructor 'enhanced'
    return new jQuery.fn.init( selector, context );
};

jQuery.fn = jQuery.prototype = {
    constructor: jQuery,
    context: null,
    isReady: null,
    init: function( selector, context ) {
        if (selector === document){
            this.context = document;
            this.selector = document;
        }
        console.log(this);
        return this;
    },
    ready: function(func){
        var args = Array.prototype.slice.call(this, arguments),
            boundReadyFunc = func.bind(this, args.slice(1));

        if (this.isReady){
            func();
        }
        else {
            document.addEventListener( "DOMContentLoaded", this.onReady.bind(this, func), false );
        }
    },
    onReady: function(func){
        console.log("onready");
        this.isReady = true;
        func.call(this);
    },
};

jQuery.fn.init.prototype = jQuery.fn;
jQuery(document).ready(function(){
    alert("Hey, here I am");
});

これがどのように機能するかを説明してみましょう。

のようなものを呼び出すたび$(selector)に、指定したオプションを使用して新しい jQuery インスタンスが作成されます ( を参照return new jQuery.fn.init( selector, context );)。

便宜上、jQuery プロトタイプを という名前の別のグローバルとして公開しjQuery.fnます。本当に連鎖可能にするには、関数は新しいインスタンスinitを返す必要があります。そのため、最後に、とjQueryの両方のプロトタイプが同じであることを明示的に定義します。このようにして、次のような関数呼び出しをチェーンできるようになりましたjQueryjQuery.init

$(document).ready(DoSomethingHere)

お役に立てれば。

また、 githubで jQuery ソースを見つけることができます。モジュール化されており、従うのは非常に簡単です。

于 2013-03-09T05:35:53.367 に答える
2

これは、関数チェーンと呼ばれるプログラミング手法です。

詳細については、こちらを参照してください: How does basic object/function chaining work in javascript?

于 2013-03-09T05:03:02.937 に答える