最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - jQuery prototype and constructor function chaining - Stack Overflow

programmeradmin1浏览0评论

How would jQuery allow its constructor to act as a function accepting arguments meanwhile its constructor also acts as a function accepting arguments?

I am a bit new to JavaScript, so excuse me if this is a noob question, (I have looked at the source but it's hard to try to dissect).

Anyway, as an example $(document).ready(<args>); Both the constructor $() and the prototype ready() act as a function. How? Because if I try this:

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 == ("plete"|"loaded"|true|4) || document.onreadystatechange() ) ? true : false;

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

I get an error Uncaught TypeError: Object[object global] has no method 'ready'

How would jQuery allow its constructor to act as a function accepting arguments meanwhile its constructor also acts as a function accepting arguments?

I am a bit new to JavaScript, so excuse me if this is a noob question, (I have looked at the source but it's hard to try to dissect).

Anyway, as an example $(document).ready(<args>); Both the constructor $() and the prototype ready() act as a function. How? Because if I try this:

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 == ("plete"|"loaded"|true|4) || document.onreadystatechange() ) ? true : false;

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

I get an error Uncaught TypeError: Object[object global] has no method 'ready'

Share Improve this question edited Nov 5, 2014 at 13:55 John Topley 115k47 gold badges199 silver badges240 bronze badges asked Mar 9, 2013 at 4:44 Jace CottonJace Cotton 2,0141 gold badge22 silver badges38 bronze badges 4
  • You're not chaining the methods by returning this from ready. – Jared Farrish Commented Mar 9, 2013 at 5:03
  • 1 I know why you're getting the error message. The $(document) is just returning the HTMLDocument, which doesn't have a .ready function. If $ had an "element" property, which stored the document element when you run the constructor, then you could check it's ready state by accessing the stored element in the ready function. – MattDiamant Commented Mar 9, 2013 at 5:04
  • @MattDiamant Ahh... I think I'll re-read that ment a few times for study. Lol. But I think I understand. Thanks. – Jace Cotton Commented Mar 9, 2013 at 5:08
  • Basically all the methods return the object they were called from. – Erik Reppen Commented Mar 9, 2013 at 5:10
Add a ment  | 

2 Answers 2

Reset to default 8

You know, this quite intrigued me. You've accepted an answer already, but let me just post mine in the event that it proves useful. There is a fiddle created here

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");
});

Let me try to explain how this works.

Every time you call something like $(selector), a new jQuery instance is created, with the options that you have provided (see return new jQuery.fn.init( selector, context ););

For the sake of convenience, we expose the jQuery prototype as another global named, jQuery.fn. To make it truly chainable, the init function must return a new jQuery instance. Which is why, at the end, we explicitly define that the prototypes for both jQuery and jQuery.init are the same. This way, you can now chain function calls like

$(document).ready(DoSomethingHere)

Hope this helps.

Also, you can find the jQuery source on github. It's modular and quite easy to follow.

It's a programming technique called function chaining.

You can see more on this here: How does basic object/function chaining work in javascript?

发布评论

评论列表(0)

  1. 暂无评论