JQuery模拟二------添加extend函数和简单选择器

在原来的基础上添加extend函数和#id选择器

//自调函数把window这个全局变量传入
(function(){
    //把jQuery和$另存一份
    var _jQuery = window.jQuery,_$ = window.$;
    //在上次的代码上添加选择器机制
    var jQuery = window.jQuery = window.$ = function(selector,context){
        return  new jQuery.fn.init(selector,context);

    }
    //对 HTML strings or ID strings进行判定
    /*可以把它看作是两个正则表达式串:
    第一个:^[^<]*(<(.|s)+>)[^>]*$
    第二个:^#(w+)$
    /^ 字符串开始
    [^<]* 匹配不包含<号的任意长度字符,长度可以为0
    (<(.|s)+ 匹配任意字符或空白符,长度必须大于等于1
    >)[^>]* 匹配不包含>号的任意字符,长度可以为0
    $ 字符串结束
    | 或
    ^ 字符串开始
    # 匹配符号#
    (w+) 匹配a-zA-z0-9,也就是所有英文字母及数字,长度大于等于1
    $/; 结束*/
    var quickExpr = /^[^<]*(<(.|s)+>)[^>]*$|^#(w+)$/;
    jQuery.fn = jQuery.prototype = {

        init:function(selector,context){
            selector=selector||document;
            context=context||document;
        //如果传入的是DOM 节点对象
        if ( selector.nodeType ) {
            this[0] = selector;
            this.length = 1;
            return this;
        }
        //对于选择器是字符串有可能是#id
        if ( typeof selector == "string" ) {
            // Are we dealing with HTML string or an ID?
            var match = quickExpr.exec(selector);
            console.log(match);
            // Verify a match, and that no context was specified for #id
            if ( match && (match[0] || !context)) {
                    var elem = document.getElementById( match[3] );
                    this.length=1;
                    return jQuery(elem);
                }
                selector = [];
            }
            //console.log("this is:"+Object.prototype.toString.call(this));
            return this;
        },
        //新增加一个方法用来取得或设置jQuery对象的html内容
        html:function(val){
            //遍历通过回调函数来设置innerHTML为val参数
            return jQuery.each(this,function(val){
                this.innerHTML=val;
            },val);
        },
        length: 0,
        jquery:"1.0.0",
        author:"BaiQiang",
        size:function(){
            return this.length;
        }
    };
    //简单的遍历函数
    jQuery.each=function(obj,callback,args){
        for(var i=0;i<obj.length;i++){
            callback.call(obj[i],args);
        }
        return obj;
    };
    //需要深入理解一下jQuery的复制函数写法
    jQuery.extend = jQuery.fn.extend = function() {
    ///    <summary>
    ///        用一个或多个其他对象来扩展一个对象,返回被扩展的对象。
    ///        用于简化继承。
    ///        jQuery.extend(settings, options);
    ///        var settings = jQuery.extend({}, defaults, options);
    ///    </summary>
    //target是被扩展的对象,默认是第一个参数(下标为0)或者是一个空对象{}
    var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
    /*如果传进来的首个参数是一个boolean类型的变量,那就证明要进行深度拷贝。
    而这时传进来的argumens[1]就是要拷贝的对象.如果是这种情况,那就要做一些"矫正"工作, 
    因为这个时候,target变量指向的是一个布尔变量而不是我们要拷贝的对象.*/
    if ( target.constructor == Boolean ) {
        deep = target;
        target = arguments[1] || {};
        //这样的话使得i=2直接跳过前两个参数
        i = 2;
    }

    // 如果target不是objet 并且也不是function 就默认设置它为{};
    if ( typeof target != "object" && typeof target != "function" )
        target = {};

    //一个参数的就是扩展jQuery对象本身
    if ( length == i ) {
        target = this;
        --i;
    }

    for ( ; i < length; i++ )
        //非null的扩展对象才把它扩展到被扩展对象上来.
        if ( (options = arguments[ i ]) != null )
            // Extend the base object
            for ( var name in options ) {
                //target是被扩展对象 options是扩展对象, 它的方法或属性将会被扩展到target上
                var src = target[ name ], copy = options[ name ];

                // target和copy如果相等还深拷贝的话就出问题了
                if ( target === copy )
                    continue;

                // Recurse if we're merging object values
                //递归src和copy深度拷贝即对每一个属性递归 
                //要是没有nodeType, 就是非Dom对象引用, 可以对它进行深度拷贝
                if ( deep && copy && typeof copy == "object" && !copy.nodeType )
                    target[ name ] = jQuery.extend( deep,
                        // Never move original objects, clone them
                        src || ( copy.length != null ? [ ] : { } )
                    , copy );

                // Don't bring in undefined values
                //如果要加进来的引用不是对象的引用(只要不是undefined ) 那就把引用加进来 
                //可能是覆盖也可能是新建name这个属性或方法
                else if ( copy !== undefined )
                    target[ name ] = copy;

            }

    //返回扩展后的被扩展对象
    return target;
};
    //使用jQuery的原型覆盖init的原型 这样就自动把jQuery.prototype的方法可以在init里面使用
    jQuery.fn.init.prototype=jQuery.fn;
})(window);

再来测试一下,给它添加一个getName()方法 然后我们调用一下它

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <script type="text/javascript" src="jquery.js"></script>
    </head>
    <body>
        <script type="text/javascript">
        jQuery.extend({
        getName: function(){
        return "bq's jQuery"
    }
});
        console.log(jQuery().jquery);
        console.log(jQuery.getName());
        </script>    
    </body>
</html>

结果如下 

1.0.0
bq's jQuery

 

原文地址:https://www.cnblogs.com/bq12345/p/3674351.html