从jQuery学到的几件事变

近来想看一下jQuery源码,搜到了如许一篇博客《从jQuery源码学到的10件事变》
http://www.paulirish.com/2010/10-things-i-learned-from-the-jquery-source/

本文基于这篇视频博客,提炼了一些内容,分享给人人。

申明:
这篇文章写于2010年,作者在视频里运用的是jQuery 1.4版本,我依据视频里讲到的内容,对应现在的1字头1.11版本做了一些调解,一些被扬弃或许被移除的内容页做了删减,并在此谢谢原作者https://github.com/paulirish

黑箱/Black box

黑箱体系的观点是给定输入返回输出的一个体系,黑箱把完成历程举行封装。这里说的jQuery黑箱是为js全局变量window输出jQuery 和 $,而历程被封装到黑箱里,与外界互不滋扰。

jQuery 1.4版本的黑箱是利用了相似以下的自实行函数

(function( window, undefined){})(window)

作者给了一个比较通用的完成黑箱的要领

undefined = true;

(function(window, document, undefined){    
    if(foo == undefined) {
        }
})(this, document)

jQuery的黑箱里多传了第三个形参叫做undefined,而传实参的时刻并没有传值,js里没有传值的形参会被设置为undefined,保证了黑箱内部undefined的正确性。js中,undefined作为一个全局属性,是能够被赋值的,比方上述代码中的undefined = true;

以自实行函数的形式完成黑箱的别的一个优点是利于紧缩,比以下述的状况,我们只须要在黑箱内部运用简朴的变量。

(function(A, B, C)){
    B.getElementById('')
})(this, document)

作者为匿名函数自实行举了许多例子,比以下面这个,为页面的某一部份不停地更新(以及不断地实行)

(function loop(){
    doStuff();

    $('#update').load('awesomething.php',function(){
        loop();
    })
    //setTimeout(loop, 100)
})()

jQuery 1.11版本的黑箱采用了全新的工场要领,本文不探讨

noConflict的完成

这个函数的差别不大,1.11 版本代码以下

var
    // Map over jQuery in case of overwrite
    _jQuery = window.jQuery,

    // Map over the $ in case of overwrite
    _$ = window.$;

jQuery.noConflict = function( deep ) {
    if ( window.$ === jQuery ) {
        window.$ = _$;
    }

    if ( deep && window.jQuery === jQuery ) {
        window.jQuery = _jQuery;
    }

    return jQuery;
};

我们能够看到防争执的完成是先把之前的JQuery 和 $ 存起来,noConflict被挪用的时刻,再还给它们

与原生js属性定名的转换

1.4版本用的是props对象来寄存jquery对属性操纵与原生js属性操纵的对应关联
1.11版缩减版本是如许的

jQuery.extend({
    propFix: {
        "for": "htmlFor",
        "class": "className"
    },

    prop: function( elem, name, value ) {
        //...
        name = jQuery.propFix[ name ] || name;
    },

    propHooks: {
        //...
    }
});

jQuery.each([
    "tabIndex",
    "readOnly",
    "maxLength",
    "cellSpacing",
    "cellPadding",
    "rowSpan",
    "colSpan",
    "useMap",
    "frameBorder",
    "contentEditable"
], function() {
    jQuery.propFix[ this.toLowerCase() ] = this;
});

propFix 这个对象是寄存对应关联表的,比方class转换成className,prop函数负责处置惩罚这个关联表。
而下面的each很有意义,遍历数组中那些属性,然后把他们小写花样对应到本身,放到 propFix

殊效Speed

我们晓得在jQuery里一些动画我们能够直接经由过程normal,fast,slow 来定义完成速率,这个在源码里是如许定义的

jQuery.fx.speeds = {
    slow: 600,
    fast: 200,
    // Default speed
    _default: 400
};

油滑的原作者做了如许一些事变:

var isIE 
//...

jQuery.fx.speeds._default = isIE ? 800 : 400
jQuery.fx.speeds.veryfast = 200;

$('...').fadeIn('veryfast')

一种是能够对default属性做前提推断,另有一种自定义速率,比方”veryfast”

.ready

ready函数 1.11版本和1.4版本有较大的差异,新版中许多东西我也不太能明白,我们就简朴的把中心拿出来看一下

jQuery.ready.promise = function( obj ) {
    //...省略多少
        } else if ( document.addEventListener ) {
            // 运用addEventListener "DOMContentLoaded" 监听ready事宜
            document.addEventListener( "DOMContentLoaded", completed, false );

            // 备选计划 "load"
            window.addEventListener( "load", completed, false );

        //假如IE
        } else {
            // Ensure firing before onload, maybe late but safe also for iframes
                        //IE下 attachEvent 的"onreadystatechange"
            document.attachEvent( "onreadystatechange", completed );

            // A fallback to window.onload, that will always work
                        //备选计划onload
            window.attachEvent( "onload", completed );

            // If IE and not a frame
            // continually check to see if the document is ready
            var top = false;

            try {
                top = window.frameElement == null && document.documentElement;
            } catch(e) {}

            if ( top && top.doScroll ) {
                (function doScrollCheck() {
                    if ( !jQuery.isReady ) {

                        try {
                            // Use the trick by Diego Perini
                            // http://javascript.nwbox.com/IEContentLoaded/
                            top.doScroll("left");
                        } catch(e) {
                            return setTimeout( doScrollCheck, 50 );
                        }

                        // detach all dom ready events
                        detach();

                        // and execute any waiting functions
                        jQuery.ready();
                    }
                })();
            }
        }
    }
    return readyList.promise( obj );
};

.ready 利用了下面的.promise去做确保载入完成的事情,重点是
document.addEventListener( "DOMContentLoaded", completed, false );
window.addEventListener( "load", completed, false );
document.attachEvent( "onreadystatechange", completed );
window.attachEvent( "onload", completed );
兼容性考量的四种搜检体式格局

个中从top最先,做了一件事变就是IE下面,dom节点推断是不是有scroll,在IE下假如dom有scroll,没有scroll到的元素对ready会有影响,这内里我的明白不够,总之jQuery里用到了一个叫做Diego Perini的技能,能够在解释里的地点看到更多内容。

选择器

$('#id').find('tag.thing') --- faster

$('#id tag.thing') ------- using sizzle

原作者在这里说了一个jquery效力的题目,上面的要领更快一些,而下面的要领轻微慢,简朴地说是由于下面的要领挪用了sizzle,经由过程sizzle实在转换成上述的形式,而id的挪用则是直接过jQuery.init.

这里须要扩大一下,我们来看一下1.11里jQuery对象终究长啥样

jQuery = function( selector, context ) {
        // The jQuery object is actually just the init constructor 'enhanced'
        // Need init if jQuery is called (just allow error to be thrown if not included)
        return new jQuery.fn.init( selector, context );
}

jQuery对象实际上是return了一个它本身的组织函数叫做init,我们再来看一下init做了些什么

// Initialize a jQuery object

    init = jQuery.fn.init = function( selector, context ) {
        var match, elem;

        // HANDLE: $(""), $(null), $(undefined), $(false)
            //超等省略...下略

        // Handle HTML strings

        // HANDLE: $(html) -> $(array)

        // HANDLE: $(html, props)

        // HANDLE: $(#id)

        // HANDLE: $(expr, $(...))

        // HANDLE: $(expr, context)

        // HANDLE: $(DOMElement)

        // HANDLE: $(function)


        return jQuery.makeArray( selector, this );
    };

// Give the init function the jQuery prototype for later instantiation
init.prototype = jQuery.fn;

从上面的摘取的代码解释中,我们能够看到jq本身的组织函数里处置惩罚了哪些状况,个中包含html标署名和id的猎取,意味着这两种猎取是最底层的,另外$()的其他处置惩罚都要经由其他的函数,效力上不如上述处置惩罚状况。
同时我们也能看到init的原型被给予了jQuery.fn, 关于jQuery对象的相关内容,感兴趣的朋侪能够再多去相识一些。

jQ的状况选择符,比方:not,:has,:eq寄存在
Sizzle.selectors.pseudos内里

    原文作者:fishenal
    原文地址: https://segmentfault.com/a/1190000000504498
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞