为什么不推荐使用“ $() . ready (Handler)”?

JQuery API 文档站点ready

以下三种语法都是等价的:

  • $(文档) . ready (处理程序)
  • $() . ready (Handler)(不推荐这样做)
  • $(处理器)

在做完家庭作业——读书和玩 源代码之后,我不知道为什么

$().ready(handler)

不建议。第一种和第三种方法完全相同,第三种方法使用 document调用缓存的 jQuery 对象上的 ready 函数:

rootjQuery = jQuery(document);
...
...


// HANDLE: $(function)
// Shortcut for document ready
} else if ( jQuery.isFunction( selector ) ) {
return rootjQuery.ready( selector );
}

但是 ready 函数与选定节点元素的选择器 ready源代码没有交互:

ready: function( fn ) {
// Attach the listeners
jQuery.bindReady();
// Add the callback
readyList.add( fn );
return this;
},

正如您所看到的,它只是将回调添加到内部队列(readyList) ,并且不更改或使用集合中的元素。这使您可以在每个 jQuery 对象上调用 ready函数。

比如:

  • 常规选择器: $('a').ready(handler) < a href = “ http://jsfiddle.net/w5k5t/1/”> DEMO
  • 荒谬选择器: $('fdhjhjkdafdsjkjriohfjdnfj').ready(handler)
  • 未定义的 选择器: $().ready(handler) < a href = “ http://jsfiddle.net/w5k5t/3/”> DEMO

最后... 回到我的问题: 为什么不推荐 $().ready(handler)

3979 次浏览

Since the different options do pretty much the same thing as you point out, it's time to put on the library writer hat and make some guesses.

  1. Perhaps the jQuery people would like to have $() available for future use (doubtful since $().ready is documented to work, even if not recommended; it would also pollute the semantics of $ if special-cased).

  2. A much more practical reason: the second version is the only one that does not end up wrapping document, so it's easier to break when maintaining the code. Example:

    // BEFORE
    $(document).ready(foo);
    
    
    // AFTER: works
    $(document).ready(foo).on("click", "a", function() {});
    

    Contrast this with

    // BEFORE
    $().ready(foo);
    
    
    // AFTER: breaks
    $().ready(foo).on("click", "a", function() {});
    
  3. Related to the above: ready is a freak in the sense that it's (the only?) method that will work the same no matter what the jQuery object wraps (even if it does not wrap anything as is the case here). This is a major difference from the semantics of other jQuery methods, so specifically relying on this is rightly discouraged.

    Update: As Esailija's comment points out, from an engineering perspective ready should really be a static method exactly because it works like this.

Update #2: Digging at the source, it seems that at some point in the 1.4 branch $() was changed to match $([]), while in 1.3 it behaved like $(document). This change would reinforce the above justifications.

I would say its simply the fact that $() returns an empty object whereas $(document) does not so your applying ready() to different things; it still works, but I would say its not intuitive.

$(document).ready(function(){}).prop("title") // the title
$().ready(function(){}).prop("title")  //null - no backing document

I think this is really more for readability than anything else.

This one isn't as expressive

$().ready(handler);

as

$(document).ready(handler)

Perhaps they are trying to promote some form of idiomatic jQuery.

Just to make it patently obvious that there is some inconsistency in the three, plus I added the fourth often used form: (function($) {}(jQuery));

With this markup:

<div >one</div>
<div>two</div>
<div id='t'/>

and this code:

var howmanyEmpty = $().ready().find('*').length;
var howmanyHandler = $(function() {}).find('*').length;
var howmanyDoc = $(document).ready().find('*').length;
var howmanyPassed = (function($) { return $('*').length; }(jQuery));
var howmanyYuck = (function($) {}(jQuery));
var howmanyYuckType = (typeof howmanyYuck);


$(document).ready(function() {
$('#t').text(howmanyEmpty + ":" + howmanyHandler + ":"
+ howmanyDoc + ":" + howmanyPassed + ":" + howmanyYuckType);
});

The displayed results of the div from the last statement are: 0:9:9:9:undefined

SO, only the Handler and Doc versions are consistent with the jQuery convention of returning something of use as they get the document selector and with the Passed form you must return something (I wouldn't do this I would think, but put it in just to show "inside" it has something).

Here is a fiddle version of this for the curious: http://jsfiddle.net/az85G/

More than likely this is just a documentation bug and should be fixed, the only downside to using $().ready(handler) is it's readability. Sure, argue that $(handler) is just as unreadable. I agree, that's why I don't use it.

You can also argue that one method is faster than another. However, how often do you call this method enough times in a row on a single page to notice a difference?

Ultimately it comes down to personal preference. There is no downside to using $().ready(handler) other than the readability argument. I think the documentation is miss-leading in this case.

I got an official answer from one of the jQuery developers:

$().ready(fn) only works because $() used to be a shortcut to $(document) (jQuery <1.4)
So $().ready(fn) was a readable code.

But people used to do things like $().mouseover() and all sorts of other madness.
and people had to do $([]) to get an empty jQuery object

So in 1.4 we changed it so $() gives an empty jQuery and we just made $().ready(fn) work so as not to break a lot of code

$().ready(fn) is literally now just patched in core to make it work properly for the legacy case.

The best place for the ready function is $.ready(fn), but it's a really old design decision and that is what we have now.


I asked him:

Do you think that $(fn) is more readable than $().ready(fn) ?!

His answer was:

I always do $(document).ready(fn) in actual apps and typically there's only one doc ready block in the app it's not exactly like a maintenance thing.

I think $(fn) is pretty unreadable too, it's just A Thing That You Have To Know Works™...