JQuery 学习模块三--$.ajax

jquery的ajax内容 https://www.w3school.com.cn/jquery/ajax_ajax.asp


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
</head>

<body>
    <form id="login">
        Email<input type="text" id="inputEmail3" name="email" placeholder="Email">
        Password<input type="password" id="inputPassword3" name="password" placeholder="Password">
        <button type="submit" onclick="sign()">Sign in</button>
    </form>

    <script>

        function sign() {
            var loginData = $("#login").serialize()//表单数据
            $.ajax({
                url: "/test04",
                data: loginData,
                type: 'POST',
                contentType: "application/x-www-form-urlencoded",
                success: function (resp) {
                    if (resp == "success") {
                        // window.location.href = "/test.html"//test.html我就不再贴出,就一行helloword
                    }
                }
            })
        }
    </script>
</body>

</html>

jQuery基本结构实现


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>04-jQuery基本结构实现</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
    <!--<script src="js/jquery-2.0.0.js"></script>-->
    <script src="js/XMGQuery-1.0.0.js"></script>

</head>
<body>
<div>div</div>
<script>
    //console.log($("div"));
    console.log(jQuery,$);
</script>
</body>
</html>
/**
 * Created by Administrator on 2018/5/27.
 */

//外层是即时函数(闭包)
(function (window,undefined) {

    //定义jQuery函数
    var jQuery = function (selector) {
        return new jQuery.prototype.init(selector);
    }

    //设置jQuery原型对象
    jQuery.prototype = {
        constructor:jQuery,
        init:function (selector) {
            //入口函数 ..
            //判断类型---> 写具体的实现
        }
    }

    //设置init的原型对象指向jQuery的原型对象
    jQuery.prototype.init.prototype = jQuery.prototype;

    //要访问闭包中的私有变量
    //(1) 直接返回该变量(函数包装)
    //(2) 把闭包中的变量绑定给全局对象
    window.jQuery = window.$ = jQuery;
})(window)

入口函数参数分析01



<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>05-入口函数参数分析01</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
    <!--<script src="js/jquery-2.0.0.js"></script>-->
    <script src="js/XMGQuery-1.0.2.js"></script>
</head>
<body>
<div>div1</div>
<div class="class1">div2</div>
<div class="class1">div3</div>

<script>
    //01 条件判断为假的情况: NaN 0 false null undefined
    //==> 返回空的jQ实例对象
    console.log($(0));
    console.log($(NaN));
    console.log($(false));
    console.log($(null));
    console.log($(undefined));


    //002 参数是字符串(标签)
    //==>  把传入的所有一级标签作为key为0,1,2...对应value值保存到jQ实例对象中

    console.log($("  <div>我是测试的标签</div>"));
    console.log($("<div>我是测试的标签1<span>我是span</span></div><div>我是测试的标签2</div> "));
    console.log($("<p1>"));


</script>

<script>
    //trim方法:去掉字符串开始和结尾的N个空格
    //string.trim()  ES5推出的,可能存在兼容性的问题
    var str1 = "abc";
    var str2 = " abc ";
    var str3 = "  abc";
    console.log(str1);
    console.log(str2,str2.trim());
    console.log(str3,str3.trim());

    function trimT(str) {
        if(str.trim)
        {
            return str.trim();
        }else
        {
            //第一个参数:匹配的字符
            //第二个参数:要替换成什么字符
            //默认只会替换一次 ==> 正则表达式
            return str.replace(/^\s+|\s+$/g,"");
        }
    }
    console.log(trimT(str2));
    console.log(trimT(str3));
</script>
</body>
</html>
/**
 * Created by Administrator on 2018/5/27.
 */

//外层是即时函数(闭包)
(function (window,undefined) {

    //定义jQuery函数
    var jQuery = function (selector) {
        return new jQuery.prototype.init(selector);
    }

    //设置jQuery原型对象
    jQuery.prototype = {
        constructor:jQuery,
        init:function (selector) {

            //入口函数 ..
            //判断类型---> 写具体的实现
            //[01] 条件判断为假==>返回空的jQ实例对象
            //this --> 指向新创建的实例对象(jQ实例对象)
            if(!selector)
            {
                return this;
            }
            //[02] 参数是字符串
            //判断:是字符串 && 标签
            //==>  把传入的所有一级标签作为key为0,1,2...对应value值保存到jQ实例对象中
            else if(Tool.isString(selector))
            {
                //容错性处理
                selector = Tool.trim(selector);
                //A 标签
                if(Tool.isHtmlStr(selector)){
                    //console.log("参数" + selector + "是标签");

                    //字符串 ---> 标签 --->依次存到this中
                    //'<div>我是测试的标签1<span>我是span</span></div><div>我是测试的标签2</div>'
                    //参考:innerHTML属性 | innerText
                    var oDiv = document.createElement("div");
                    oDiv.innerHTML = selector;

                    //获取临时标签的子节点
                    var nodes = oDiv.children;
                    for(var i = 0; i<nodes.length;i++)
                    {
                        this[i] = nodes[i];
                    }
                    //更新length属性
                    this.length = nodes.length;
                    return this;
                }
                //B 选择器
                else
                {

                }
            }

        }
    }

    //设置init的原型对象指向jQuery的原型对象
    jQuery.prototype.init.prototype = jQuery.prototype;

    //要访问闭包中的私有变量
    //(1) 直接返回该变量(函数包装)
    //(2) 把闭包中的变量绑定给全局对象
    window.jQuery = window.$ = jQuery;

    //工具方法
    var Tool = {
        isString:function (str) {
        return typeof str === "string"
    },
        isHtmlStr:function (htmlStr) {
        //(1) 以<开头
        //(2) 以>结尾
        //(3) 长度>=3
        return htmlStr.charAt(0) === "<" && htmlStr.charAt(htmlStr.length-1) ===">" && htmlStr.length >=3
    },
        trim:function (str) {
            if(str.trim)
            {
                return str.trim();
            }else
            {
                return str.replace(/^\s+|\s+$/g,"");
            }
        }
    }

})(window)

选择器处理


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>05-入口函数参数分析01</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
    <!--<script src="js/jquery-2.0.0.js"></script>-->
    <script src="js/XMGQuery-1.0.3.js"></script>
</head>
<body>
<div>div1</div>
<div class="class1">div2</div>
<div class="class1">div3</div>

<script>
    //参数是字符串(选择器): div #ID .class1
    //==> 根据参数获取页面中对应的标签,然后把它们作为key为0,1,2...对应的value保存到jQ实例对象中返回
    console.log($("div"));
    console.log($(".class1"));
</script>

</body>
</html>
/**
 * Created by Administrator on 2018/5/27.
 */

//外层是即时函数(闭包)
(function (window,undefined) {

    //定义jQuery函数
    var jQuery = function (selector) {
        return new jQuery.prototype.init(selector);
    }

    //设置jQuery原型对象
    jQuery.prototype = {
        constructor:jQuery,
        init:function (selector) {

            //入口函数 ..
            //判断类型---> 写具体的实现
            //[01] 条件判断为假==>返回空的jQ实例对象
            //this --> 指向新创建的实例对象(jQ实例对象)
            if(!selector)
            {
                return this;
            }
            //[02] 参数是字符串
            //判断:是字符串 && 标签
            //==>  把传入的所有一级标签作为key为0,1,2...对应value值保存到jQ实例对象中
            else if(Tool.isString(selector))
            {
                //容错性处理
                selector = Tool.trim(selector);
                //A 标签
                if(Tool.isHtmlStr(selector)){
                    //console.log("参数" + selector + "是标签");

                    //字符串 ---> 标签 --->依次存到this中
                    //'<div>我是测试的标签1<span>我是span</span></div><div>我是测试的标签2</div>'
                    //参考:innerHTML属性 | innerText
                    var oDiv = document.createElement("div");
                    oDiv.innerHTML = selector;

                    //获取临时标签的子节点
                    var nodes = oDiv.children;

                    //总结:遍历数组把数组中每个元素依次取出保存到this对象中,更新length
                    // for(var i = 0; i<nodes.length;i++)
                    // {
                    //     this[i] = nodes[i];
                    // }
                    // //更新length属性
                    // this.length = nodes.length;

                    //[].push.call(this,nodes); ==> this.push(nodes);
                    return this;
                }
                //B 选择器
                else
                {
                    //"div" | ".className" |"#demoID"
                    //(1)根据参数获取页面中对应的标签
                    //document.getElementsByTagName("div");
                    //document.getElementById("#demoID");
                    //document.getElementsByClassName(".className")
                    var nodes = document.querySelectorAll(selector);
                    //(2)然后把它们作为key为0,1,2...对应的value保存到jQ实例对象中返回
                    for(var i = 0;i<nodes.length;i++)
                    {
                        this[i] = nodes[i];
                    }
                    //更新length的值
                    this.length = nodes.length;
                    return this;
                }
            }

        }
    }

    //设置init的原型对象指向jQuery的原型对象
    jQuery.prototype.init.prototype = jQuery.prototype;

    //要访问闭包中的私有变量
    //(1) 直接返回该变量(函数包装)
    //(2) 把闭包中的变量绑定给全局对象
    window.jQuery = window.$ = jQuery;

    //工具方法
    var Tool = {
        isString:function (str) {
        return typeof str === "string"
    },
        isHtmlStr:function (htmlStr) {
        //(1) 以<开头
        //(2) 以>结尾
        //(3) 长度>=3
        return htmlStr.charAt(0) === "<" && htmlStr.charAt(htmlStr.length-1) ===">" && htmlStr.length >=3
    },
        trim:function (str) {
            if(str.trim)
            {
                return str.trim();
            }else
            {
                return str.replace(/^\s+|\s+$/g,"");
            }
        }
    }

})(window)

参数是伪数组


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>05-入口函数参数分析01</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
    <!--<script src="js/jquery-2.0.0.js"></script>-->
    <script src="js/XMGQuery-1.0.5.js"></script>
</head>
<body>
<div>div1</div>
<div class="class1">div2</div>
<div class="class1">div3</div>

<script>
    /*
    java 函数重载:同一个函数传递不同的参数会执行不同的操作*/
    //01 条件判断为假的情况: NaN 0 false null undefined
    //==> 返回空的jQ实例对象
    console.log($(0));
    console.log($(NaN));
    console.log($(false));
    console.log($(null));
    console.log($(undefined));

    //002 参数是字符串(选择器): div #ID .class1
    //==> 根据参数获取页面中对应的标签,然后把它们作为key为0,1,2...对应的value保存到jQ实例对象中返回
    console.log($("div"));
    console.log($(".class1"));

    //003 参数是字符串(标签)
    //==>  把传入的所有一级标签作为key为0,1,2...对应value值保存到jQ实例对象中
    console.log($("<div>我是测试的标签</div>"));
    console.log($("<div>我是测试的标签1<span>我是span</span></div><div>我是测试的标签2</div>"));
    console.log("___");

    //004 参数是数组
    //==> 遍历传入的数组,把数组中每个元素都作为key为0,1,2...对应value值保存到jQ实例对象中
    console.log($([1, 2, 3, 4, 6]));
    console.log($(["demo1", "demo2", "demo3"]));


    //005 参数是伪数组
    //(1) key从0开始依次递增(但是允许存在其他的key,在处理的时候会被忽略)
    //(2) 拥有length属性,拥有length-1键值对
    //(3) 本身是对象不是数组
    var obj1 = {0:"name",1:"age",2:"color",3:"des","length":4};  //伪数组
    var obj2 = {0:"name",1:"age",2:"color",3:"des","length":5};  //普通对象不是伪数组
    var obj3 = {0:"name",1:"age",2:"color",3:"des","length":4,"info":"哈哈哈哈哈"}; //伪数组

    //console.log(obj1);
    //console.log([1, 2, 3, 4, 6]);
    console.log("___");
    console.log($(obj1));
    console.log($(obj2));
    console.log($(obj3));

    //window
    //console.log(window.length);
    //console.log(window == window.window);
</script>

</body>
</html>
/**
 * Created by Administrator on 2018/5/27.
 */

//外层是即时函数(闭包)
(function (window,undefined) {

    //定义jQuery函数
    var jQuery = function (selector) {
        return new jQuery.prototype.init(selector);
    }

    //设置jQuery原型对象
    jQuery.prototype = {
        constructor:jQuery,
        init:function (selector) {

            //入口函数 ..
            //判断类型---> 写具体的实现
            //[01] 条件判断为假==>返回空的jQ实例对象
            //this --> 指向新创建的实例对象(jQ实例对象)
            if(!selector)
            {
                return this;
            }
            //[02] 参数是字符串
            //判断:是字符串 && 标签
            //==>  把传入的所有一级标签作为key为0,1,2...对应value值保存到jQ实例对象中
            else if(Tool.isString(selector))
            {
                //容错性处理
                selector = Tool.trim(selector);
                //A 标签
                if(Tool.isHtmlStr(selector)){

                    //根据参数获取所有的一级标签
                    var oDiv = document.createElement("div");
                    oDiv.innerHTML = selector;

                    //总结:遍历数组把数组中每个元素依次取出保存到this对象中,更新length
                    [].push.apply(this,oDiv.children);
                }
                //B 选择器
                else
                {
                    //根据参数获取页面中对应的标签
                    //然后把它们作为key为0,1,2...对应的value保存到jQ实例对象中返回
                    [].push.apply(this,document.querySelectorAll(selector));
                }
            }
            //[03] 参数是数组
            else if(Tool.isArray(selector))
            {
                //遍历传入的数组,把数组中每个元素都作为key为0,1,2...对应value值保存到jQ实例对象中
                [].push.apply(this,selector);
            }
            //[04] 参数是伪数组
            else if(Tool.isLikeArray(selector))
            {
                //遍历伪数组,把对象中每个value值都作为key为0,1,2...对应value值保存到jQ实例对象中
                [].push.apply(this,selector);
            }

        }
    }

    //设置init的原型对象指向jQuery的原型对象
    jQuery.prototype.init.prototype = jQuery.prototype;

    //要访问闭包中的私有变量
    //(1) 直接返回该变量(函数包装)
    //(2) 把闭包中的变量绑定给全局对象
    window.jQuery = window.$ = jQuery;

    //工具方法
    var Tool = {
        isWindow:function (obj) {
           return obj != null && obj == obj.window;
        },
        isObject:function (obj) {
          return typeof obj === "object" && obj != null && !this.isArray(obj)
        },
        isString:function (str) {
        return typeof str === "string"
    },
        isHtmlStr:function (htmlStr) {
        //(1) 以<开头
        //(2) 以>结尾
        //(3) 长度>=3
        return htmlStr.charAt(0) === "<" && htmlStr.charAt(htmlStr.length-1) ===">" && htmlStr.length >=3
    },
        isArray:function (arr) {
            if(Array.isArray)
            {
                return Array.isArray(arr);
            }else
            {
                return Object.prototype.toString.call(arr) === "[object Array]";
            }
        },
        isLikeArray:function (obj) {
            //(1) key从0开始依次递增(但是允许存在其他的key,在处理的时候会被忽略)
            //(2) 拥有length属性,拥有length-1键值对
            //(3) 本身是对象不是数组
            return this.isObject(obj) && "length" in obj && obj.length-1 in obj && !this.isWindow(obj)
        },
        trim:function (str) {
            if(str.trim)
            {
                return str.trim();
            }else
            {
                return str.replace(/^\s+|\s+$/g,"");
            }
        }
    }

})(window)

伪数组处理


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>05-入口函数参数分析01</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
    <!--<script src="js/jquery-2.0.0.js"></script>-->
    <!--<script src="js/XMGQuery-1.0.6.js"></script>-->
</head>
<body>
<div>div1</div>
<div class="class1">div2</div>
<div class="class1">div3</div>

<script>
    //问题:在IE中 [].push.apply(this,伪数组); 存在问题
    //伪数组分类: 系统的伪数组(正常) |  自定义的伪数组(会报错)
    var nodes = document.getElementsByTagName("div");
    var obj1 = {0:"name",1:"age","length":2}; //==>["name","age"];
    console.log(nodes);
    console.log(obj1);

    var objA = {name:"objA"};
    var objB = {name:"objB"};
    [].push.apply(objA,nodes);   //正确
    [].push.apply(objB,obj1);    //报错

    console.log(objA);
    console.log(objB);


    //apply:数组  正确处理
    //apply:系统的伪数组  正确处理
    //apply:自定义的伪数组 报错(IE)

</script>
<script>
    var obj = {0:"name",1:"age","length":2};
    var arrM = [];
    for (var i = 0;i<obj.length;i++)
    {
        arrM.push(obj[i]);
    }
    console.log(arrM);
</script>
</body>
</html>

/**
 * Created by Administrator on 2018/5/27.
 */

//外层是即时函数(闭包)
(function (window,undefined) {

    //定义jQuery函数
    var jQuery = function (selector) {
        return new jQuery.prototype.init(selector);
    }

    //设置jQuery原型对象
    jQuery.fn = jQuery.prototype = {
        constructor:jQuery,
        init:function (selector) {

            //入口函数 ..
            //判断类型---> 写具体的实现

            //[00] 条件判断为假==>返回空的jQ实例对象
            //this --> 指向新创建的实例对象(jQ实例对象)
            if(!selector)
            {
                return this;
            }
            //[01] 参数是函数
            else if($.isFunction(selector))
            {
                this.ready(selector);
            }
            //[02] 参数是字符串
            //判断:是字符串 && 标签
            //==>  把传入的所有一级标签作为key为0,1,2...对应value值保存到jQ实例对象中
            else if($.isString(selector))
            {
                //容错性处理
                selector = $.trim(selector);
                //A 标签
                if($.isHtmlStr(selector)){

                    //根据参数获取所有的一级标签
                    var oDiv = document.createElement("div");
                    oDiv.innerHTML = selector;

                    //总结:遍历数组把数组中每个元素依次取出保存到this对象中,更新length
                    [].push.apply(this,oDiv.children);
                }
                //B 选择器
                else
                {
                    //根据参数获取页面中对应的标签
                    //然后把它们作为key为0,1,2...对应的value保存到jQ实例对象中返回
                    [].push.apply(this,document.querySelectorAll(selector));
                }
            }
            //[03] 参数是数组或者是伪数组
            else if($.isArray(selector) || $.isLikeArray(selector))
            {
                var arrM = [].slice.call(selector);
                [].push.apply(this,arrM);
            }
            //[04] 其它情况
            else {
                //DOM | 非0的数字 | true
                //把(selector)整体作为key为0对应的value值保存到jQ实例对象中返回
                this[0] = selector;
                this.length = 1;
            }

        },
        ready:function (fn) {

            if(document.readyState === "complete")
            {
                fn();
                return;
            }

            //监听DOM加载,调用函数
            //if(DOM加载完) selector();
            if(document.addEventListener)
            {
                document.addEventListener("DOMContentLoaded",fn);
            }else {
                document.attachEvent("onreadystatechange",function () {
                    if(document.readyState === "complete")
                    {
                        fn();
                    }
                })
            }
        },
        isTest1:function () {
            console.log("测试的方法");
        },
        isTest2:function () {
            console.log("测试的方法");
        },
    }

    //设置init的原型对象指向jQuery的原型对象
    jQuery.prototype.init.prototype = jQuery.prototype;

    //要访问闭包中的私有变量
    //(1) 直接返回该变量(函数包装)
    //(2) 把闭包中的变量绑定给全局对象
    window.jQuery = window.$ = jQuery;

    //工具方法
    //声明了两个方法
    jQuery.fn.extend = jQuery.extend = function (obj) {
        for(var key in obj)
        {
            if(typeof obj[key] === "function" && obj.hasOwnProperty(key))
            {
                this[key] = obj[key];
            }
        }
    }

    jQuery.extend({
        isWindow:function (obj) {
            return obj != null && obj == obj.window;
        },
        isObject:function (obj) {
            return typeof obj === "object" && obj != null && !this.isArray(obj)
        },
        isString:function (str) {
            return typeof str === "string"
        },
        isHtmlStr:function (htmlStr) {
            //(1) 以<开头
            //(2) 以>结尾
            //(3) 长度>=3
            return htmlStr.charAt(0) === "<" && htmlStr.charAt(htmlStr.length-1) ===">" && htmlStr.length >=3
        },
        isArray:function (arr) {
            if(Array.isArray)
            {
                return Array.isArray(arr);
            }else
            {
                return Object.prototype.toString.call(arr) === "[object Array]";
            }
        },
        isLikeArray:function (obj) {
            //(1) key从0开始依次递增(但是允许存在其他的key,在处理的时候会被忽略)
            //(2) 拥有length属性,拥有length-1键值对
            //(3) 本身是对象不是数组
            return this.isObject(obj) && "length" in obj && obj.length-1 in obj && !this.isWindow(obj)
        },
        trim:function (str) {
            if(str.trim)
            {
                return str.trim();
            }else
            {
                return str.replace(/^\s+|\s+$/g,"");
            }
        },
        isFunction:function (fn) {
            return typeof fn === "function";
        }
    });

    jQuery.fn.extend({
        isB:function () {

        }
    })

})(window)

函数作为参数处理


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>03-函数作为参数处理01</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
    <script src="js/XMGQuery-1.0.9.js"></script>

</head>
<body>

<script>
    //函数作为jQuery函数的参数的使用情况
    //语法:
    // $(document).ready(function () {//....})
    // $(function () {//....})
    //作用:监听DOM的加载,等DOM准备好执行函数中的内容.和window.onload类似
    //和原生监听方式的区别:
    //(1) 监听时机不同
    //(2) 监听多次,执行次数不同
    //    原生:监听DOM加载,等所有的资源(CSS | JS | IMG ..)都加载完毕才执行函数
    //         执行执行1次,覆盖
    //    jQ : 监听DOM加载,等DOM准备好就执行函数
    //         执行N次,没有覆盖问题

    //实现思路:
    //[1] 检测参数是否是函数      typeof fn === "function"
    //[2] 监听DOM是否准备好,如果准备好,执行(调用)该函数

    //核心问题:
    //如何监听DOM是否加载完毕(准备好了?)
    //DOMContentLoaded DOM树已经构造完成
    //第一个参数:要监听的具体的过程(DOMContentLoaded)
    //第二个参数:回调函数(当事件发生执行回调函数)
//    document.addEventListener("DOMContentLoaded",function () {
//        var oDiv = document.getElementsByTagName("div")[0];
//        console.log(oDiv);
//        console.log("DOM构造完成");
//    })

    //addEventListener兼容性处理(IE9-)
    //attachEvent监听
    //第一个参数:状态发生改变(字符串) 状态
    //第二个参数:回调函数
//    document.attachEvent("onreadystatechange",function () {
//        //console.log(document.readyState);
//        if(document.readyState === "complete")
//        {
//            var oDiv = document.getElementsByTagName("div")[0];
//            console.log(oDiv);
//        }
//    })

    $(function () {
        var oDiv = document.getElementsByTagName("div")[0];
        console.log(oDiv);
    })

    $(document).ready(function () {
        var oDiv = document.getElementsByTagName("div")[0];
        console.log(oDiv);
    })



</script>
<div>divT</div>
</body>
</html>
/**
 * Created by Administrator on 2018/5/27.
 */

//外层是即时函数(闭包)
(function (window,undefined) {

    //定义jQuery函数
    var jQuery = function (selector) {
        return new jQuery.prototype.init(selector);
    }

    //设置jQuery原型对象
    jQuery.prototype = {
        constructor:jQuery,
        init:function (selector) {

            //入口函数 ..
            //判断类型---> 写具体的实现

            //[00] 条件判断为假==>返回空的jQ实例对象
            //this --> 指向新创建的实例对象(jQ实例对象)
            if(!selector)
            {
                return this;
            }
            //[01] 参数是函数
            else if(Tool.isFunction(selector))
            {
                this.ready(selector);
            }
            //[02] 参数是字符串
            //判断:是字符串 && 标签
            //==>  把传入的所有一级标签作为key为0,1,2...对应value值保存到jQ实例对象中
            else if(Tool.isString(selector))
            {
                //容错性处理
                selector = Tool.trim(selector);
                //A 标签
                if(Tool.isHtmlStr(selector)){

                    //根据参数获取所有的一级标签
                    var oDiv = document.createElement("div");
                    oDiv.innerHTML = selector;

                    //总结:遍历数组把数组中每个元素依次取出保存到this对象中,更新length
                    [].push.apply(this,oDiv.children);
                }
                //B 选择器
                else
                {
                    //根据参数获取页面中对应的标签
                    //然后把它们作为key为0,1,2...对应的value保存到jQ实例对象中返回
                    [].push.apply(this,document.querySelectorAll(selector));
                }
            }
            //[03] 参数是数组或者是伪数组
            else if(Tool.isArray(selector) || Tool.isLikeArray(selector))
            {
                var arrM = [].slice.call(selector);
                [].push.apply(this,arrM);
            }
            //[04] 其它情况
            else {
                //DOM | 非0的数字 | true
                //把(selector)整体作为key为0对应的value值保存到jQ实例对象中返回
                this[0] = selector;
                this.length = 1;
            }

        },
        ready:function (fn) {

            if(document.readyState === "complete")
            {
                fn();
                return;
            }

            //监听DOM加载,调用函数
            //if(DOM加载完) selector();
            if(document.addEventListener)
            {
                document.addEventListener("DOMContentLoaded",fn);
            }else {
                document.attachEvent("onreadystatechange",function () {
                    if(document.readyState === "complete")
                    {
                        fn();
                    }
                })
            }
        },
    }

    //设置init的原型对象指向jQuery的原型对象
    jQuery.prototype.init.prototype = jQuery.prototype;

    //要访问闭包中的私有变量
    //(1) 直接返回该变量(函数包装)
    //(2) 把闭包中的变量绑定给全局对象
    window.jQuery = window.$ = jQuery;

    //工具方法
    var Tool = {
        isWindow:function (obj) {
           return obj != null && obj == obj.window;
        },
        isObject:function (obj) {
          return typeof obj === "object" && obj != null && !this.isArray(obj)
        },
        isString:function (str) {
        return typeof str === "string"
    },
        isHtmlStr:function (htmlStr) {
        //(1) 以<开头
        //(2) 以>结尾
        //(3) 长度>=3
        return htmlStr.charAt(0) === "<" && htmlStr.charAt(htmlStr.length-1) ===">" && htmlStr.length >=3
    },
        isArray:function (arr) {
            if(Array.isArray)
            {
                return Array.isArray(arr);
            }else
            {
                return Object.prototype.toString.call(arr) === "[object Array]";
            }
        },
        isLikeArray:function (obj) {
            //(1) key从0开始依次递增(但是允许存在其他的key,在处理的时候会被忽略)
            //(2) 拥有length属性,拥有length-1键值对
            //(3) 本身是对象不是数组
            return this.isObject(obj) && "length" in obj && obj.length-1 in obj && !this.isWindow(obj)
        },
        trim:function (str) {
            if(str.trim)
            {
                return str.trim();
            }else
            {
                return str.replace(/^\s+|\s+$/g,"");
            }
        },
        isFunction:function (fn) {
            return typeof fn === "function";
        }
    }

    //jQuery.Tool = Tool;
    /*
    jQuery.trim = function (str) {
        if(str.trim)
        {
            return str.trim();
        }else
        {
            return str.replace(/^\s+|\s+$/g,"");
        }
    }
    jQuery.isLikeArray = function (obj) {
        //(1) key从0开始依次递增(但是允许存在其他的key,在处理的时候会被忽略)
        //(2) 拥有length属性,拥有length-1键值对
        //(3) 本身是对象不是数组
        return Tool.isObject(obj) && "length" in obj && obj.length-1 in obj && !Tool.isWindow(obj)
    }
    */
    function copyToolFn(obj) {
        for(var key in obj)
        {
            if(typeof obj[key] === "function" && obj.hasOwnProperty(key))
            {
                jQuery[key] = obj[key];
            }
        }
    }

    var Tool2 = {
        isGoodMan:function () {
            console.log("你是个好人,但是我不喜欢");
        }
    }

    copyToolFn(Tool);
    copyToolFn(Tool2);

})(window)

工具方法优化处理


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>05-工具方法优化处理</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
    <!--<script src="js/jquery-2.0.0.js"></script>-->
    <script src="js/XMGQuery-1.1.0.js"></script>
</head>
<body>

<script>
    //工具方法的处理
    //(1) 把工具方法添加作为jQuery静态方法来用 $.trim()
    //(2) 把工具方法添加作为jQuery原型方法来用 $().css()

    //总结
    //如果该方法在操作的时候和jQ实例对象没有什么关系,那么建议写成静态方法
    //如果该方法在操作的时候需要依赖于jQ对象,需要操作该对象,那么建议写成原型方法
    //如果该方法需要同时适用上面的两种情况,那么建议既写成静态方法又写成原型方法

    //插件核心写法
    //新创建js文件:jQuery.插件名字.js
    //在该文件中调用插件扩展方法来显示 :
    //jQuery.fn.extend({//})  $().方法();
    //jQuery.extent({//})     $.方法();
</script>
</body>
</html>
/**
 * Created by Administrator on 2018/5/27.
 */

//外层是即时函数(闭包)
(function (window,undefined) {

    //定义jQuery函数
    var jQuery = function (selector) {
        return new jQuery.prototype.init(selector);
    }

    //设置jQuery原型对象
    jQuery.fn = jQuery.prototype = {
        constructor:jQuery,
        init:function (selector) {

            //入口函数 ..
            //判断类型---> 写具体的实现

            //[00] 条件判断为假==>返回空的jQ实例对象
            //this --> 指向新创建的实例对象(jQ实例对象)
            if(!selector)
            {
                return this;
            }
            //[01] 参数是函数
            else if($.isFunction(selector))
            {
                this.ready(selector);
            }
            //[02] 参数是字符串
            //判断:是字符串 && 标签
            //==>  把传入的所有一级标签作为key为0,1,2...对应value值保存到jQ实例对象中
            else if($.isString(selector))
            {
                //容错性处理
                selector = $.trim(selector);
                //A 标签
                if($.isHtmlStr(selector)){

                    //根据参数获取所有的一级标签
                    var oDiv = document.createElement("div");
                    oDiv.innerHTML = selector;

                    //总结:遍历数组把数组中每个元素依次取出保存到this对象中,更新length
                    [].push.apply(this,oDiv.children);
                }
                //B 选择器
                else
                {
                    //根据参数获取页面中对应的标签
                    //然后把它们作为key为0,1,2...对应的value保存到jQ实例对象中返回
                    [].push.apply(this,document.querySelectorAll(selector));
                }
            }
            //[03] 参数是数组或者是伪数组
            else if($.isArray(selector) || $.isLikeArray(selector))
            {
                var arrM = [].slice.call(selector);
                [].push.apply(this,arrM);
            }
            //[04] 其它情况
            else {
                //DOM | 非0的数字 | true
                //把(selector)整体作为key为0对应的value值保存到jQ实例对象中返回
                this[0] = selector;
                this.length = 1;
            }

        },
        ready:function (fn) {

            if(document.readyState === "complete")
            {
                fn();
                return;
            }

            //监听DOM加载,调用函数
            //if(DOM加载完) selector();
            if(document.addEventListener)
            {
                document.addEventListener("DOMContentLoaded",fn);
            }else {
                document.attachEvent("onreadystatechange",function () {
                    if(document.readyState === "complete")
                    {
                        fn();
                    }
                })
            }
        },
        isTest1:function () {
            console.log("测试的方法");
        },
        isTest2:function () {
            console.log("测试的方法");
        },
    }

    //设置init的原型对象指向jQuery的原型对象
    jQuery.prototype.init.prototype = jQuery.prototype;

    //要访问闭包中的私有变量
    //(1) 直接返回该变量(函数包装)
    //(2) 把闭包中的变量绑定给全局对象
    window.jQuery = window.$ = jQuery;

    //工具方法
    //声明了两个方法
    jQuery.fn.extend = jQuery.extend = function (obj) {
        for(var key in obj)
        {
            if(typeof obj[key] === "function" && obj.hasOwnProperty(key))
            {
                this[key] = obj[key];
            }
        }
    }
    jQuery.extend({
        isWindow:function (obj) {
            return obj != null && obj == obj.window;
        },
        isObject:function (obj) {
            return typeof obj === "object" && obj != null && !this.isArray(obj)
        },
        isString:function (str) {
            return typeof str === "string"
        },
        isHtmlStr:function (htmlStr) {
            //(1) 以<开头
            //(2) 以>结尾
            //(3) 长度>=3
            return htmlStr.charAt(0) === "<" && htmlStr.charAt(htmlStr.length-1) ===">" && htmlStr.length >=3
        },
        isArray:function (arr) {
            if(Array.isArray)
            {
                return Array.isArray(arr);
            }else
            {
                return Object.prototype.toString.call(arr) === "[object Array]";
            }
        },
        isLikeArray:function (obj) {
            //(1) key从0开始依次递增(但是允许存在其他的key,在处理的时候会被忽略)
            //(2) 拥有length属性,拥有length-1键值对
            //(3) 本身是对象不是数组
            return this.isObject(obj) && "length" in obj && obj.length-1 in obj && !this.isWindow(obj)
        },
        trim:function (str) {
            if(str.trim)
            {
                return str.trim();
            }else
            {
                return str.replace(/^\s+|\s+$/g,"");
            }
        },
        isFunction:function (fn) {
            return typeof fn === "function";
        }
    });
    jQuery.fn.extend({
        isB:function () {

        }
    })

})(window)

属性和属性节点


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>13-属性和属性节点</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
    <!--<script src="js/jquery-2.0.0.js"></script>-->
    <script src="js/XMGQuery-1.3.0.js"></script>

</head>
<body>
<div class="div-class1" a="A">我是div1</div>
<div class="div-class2" b="B">我是div2</div>
<script>
    //属性和属性节点
    //属性节点:class | a | b
    //属性节点保存在节点的attributes属性中
    //属性直接保存到DOM节点自己身上

    //attr
    //作用:添加|修改|查询指定标签的属性节点
    //语法:
    //$().attr(key,value)      批量的添加|修改所有指定标签对应的属性节点
    //$().attr(key)            获取指定标签(第一个)对应属性节点的值
    //$().attr(obj)            批量设置

    //console.log($("div").attr());
    //console.log($("div").attr("a"));
    //$("div").attr("class","xxxx");
    $("div").attr({"xxx":"xxxx","ddd":"dddd"});

    //实现思路:
    //参数情况分析
    //[1] 0个参数 ||  参数既不是字符串也不是对象   ==> 报错
    //[2] 1个参数
    //    001 字符串      获取指定标签(第一个)对应属性节点的值
    //    002 对象        批量设置
    //[3] 2个参数         批量的添加|修改所有指定标签对应的属性节点
</script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>13-属性和属性节点</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
    <!--<script src="js/jquery-2.0.0.js"></script>-->
    <script src="js/XMGQuery-1.3.1.js"></script>

</head>
<body>
<div class="div-class1" a="A">我是div1</div>
<div class="div-class2" b="B">我是div2</div>
<script>

    //attr
    //作用:添加|修改|查询指定标签的属性节点
    //语法:
    //$().attr(key,value)      批量的添加|修改所有指定标签对应的属性节点
    //$().attr(key)            获取指定标签(第一个)对应属性节点的值
    //$().attr(obj)            批量设置

    //removeAttr
    //作用:删除指定标签中对应的属性节点
    //$().removeAttr(key)
    console.log($("div").removeAttr("a"));
</script>
</body>
</html>
/**
 * Created by Administrator on 2018/5/27.
 */

//外层是即时函数(闭包)
(function (window,undefined) {

    //定义jQuery函数
    var jQuery = function (selector) {
        return new jQuery.prototype.init(selector);
    }

    //设置jQuery原型对象
    jQuery.fn = jQuery.prototype = {
        constructor:jQuery,
        jquery:"v 1.2.0",
        selector:"",
        length:0,
        init:function (selector) {

            //入口函数 ..
            //判断类型---> 写具体的实现

            //[00] 条件判断为假==>返回空的jQ实例对象
            //this --> 指向新创建的实例对象(jQ实例对象)
            if(!selector)
            {
                return this;
            }
            //[01] 参数是函数
            else if($.isFunction(selector))
            {
                this.ready(selector);
            }
            //[02] 参数是字符串
            //判断:是字符串 && 标签
            //==>  把传入的所有一级标签作为key为0,1,2...对应value值保存到jQ实例对象中
            else if($.isString(selector))
            {
                //容错性处理
                selector = $.trim(selector);
                //A 标签
                if($.isHtmlStr(selector)){

                    //根据参数获取所有的一级标签
                    var oDiv = document.createElement("div");
                    oDiv.innerHTML = selector;

                    //总结:遍历数组把数组中每个元素依次取出保存到this对象中,更新length
                    [].push.apply(this,oDiv.children);
                }
                //B 选择器
                else
                {
                    //根据参数获取页面中对应的标签
                    //然后把它们作为key为0,1,2...对应的value保存到jQ实例对象中返回
                    [].push.apply(this,document.querySelectorAll(selector));
                }
            }
            //[03] 参数是数组或者是伪数组
            else if($.isArray(selector) || $.isLikeArray(selector))
            {
                var arrM = [].slice.call(selector);
                [].push.apply(this,arrM);
            }
            //[04] 其它情况
            else {
                //DOM | 非0的数字 | true
                //把(selector)整体作为key为0对应的value值保存到jQ实例对象中返回
                this[0] = selector;
                this.length = 1;
            }

        },
        ready:function (fn) {

            if(document.readyState === "complete")
            {
                fn();
                return;
            }

            //监听DOM加载,调用函数
            //if(DOM加载完) selector();
            if(document.addEventListener)
            {
                document.addEventListener("DOMContentLoaded",fn);
            }else {
                document.attachEvent("onreadystatechange",function () {
                    if(document.readyState === "complete")
                    {
                        fn();
                    }
                })
            }
        },
        toArray:function () {
            //作用:把jQ实例对象 --> 数组返回
            //this
            //console.log("this",this);
            return [].slice.call(this);
        },
        get:function (index) {
            //获取this中索引为index的标签返回
            //[0] 没有参数,返回数组
            if(arguments.length === 0)
            {
                return this.toArray();
            }else if(arguments.length ===1 && typeof index === "number") {
                    //[1] 参数是正数
                if (index >= 0) {
                    return this[index];
                } else
                {
                    //[2] 参数是负数
                    //-1 倒数第一个    索引为3 == length + (-1)
                    //-2 倒数第二个    索引为2 == length + (-2)
                    //-3 倒数第三个    索引为1 == length + (-3)
                    return this[this.length + index];
                }
            }
        },
        eq:function (index) {
            if(index == undefined)
            {
                return $();
            }
            else if(arguments.length ===1 && typeof index === "number")
            {
                /*
                if (index >= 0) {
                    return $(this[index]);
                } else
                {
                    return $(this[this.length + index]);
                }*/
                return $(this.get(index));
            }
        },
        first:function () {
            return this.eq(0);
        },
        last:function () {
            return this.eq(-1)
        },
        sort: [].sort,
        splice: [].splice,
        each:function (fn) {
           jQuery.each(this,fn);
        }
    }

    //设置init的原型对象指向jQuery的原型对象
    jQuery.prototype.init.prototype = jQuery.prototype;

    //插件扩展方法
    //声明了两个方法,函数体中的this由调用上下文决定
    jQuery.fn.extend = jQuery.extend = function (obj) {
        for(var key in obj)
        {
            if(typeof obj[key] === "function" && obj.hasOwnProperty(key))
            {
                this[key] = obj[key];
            }
        }
    }

    //常用工具方法(jQuery静态方法)
    jQuery.extend({
        isWindow:function (obj) {
            return obj != null && obj == obj.window;
        },
        isObject:function (obj) {
            return typeof obj === "object" && obj != null && !this.isArray(obj)
        },
        isString:function (str) {
            return typeof str === "string"
        },
        isHtmlStr:function (htmlStr) {
            //(1) 以<开头
            //(2) 以>结尾
            //(3) 长度>=3
            return htmlStr.charAt(0) === "<" && htmlStr.charAt(htmlStr.length-1) ===">" && htmlStr.length >=3
        },
        isArray:function (arr) {
            if(Array.isArray)
            {
                return Array.isArray(arr);
            }else
            {
                return Object.prototype.toString.call(arr) === "[object Array]";
            }
        },
        isLikeArray:function (obj) {
            //(1) key从0开始依次递增(但是允许存在其他的key,在处理的时候会被忽略)
            //(2) 拥有length属性,拥有length-1键值对
            //(3) 本身是对象不是数组
            return this.isObject(obj) && "length" in obj && obj.length-1 in obj && !this.isWindow(obj)
        },
        trim:function (str) {
            if(str.trim)
            {
                return str.trim();
            }else
            {
                return str.replace(/^\s+|\s+$/g,"");
            }
        },
        isFunction:function (fn) {
            return typeof fn === "function";
        }
    });

    //each和map方法(jQuery静态方法)
    jQuery.extend({
        each:function (objT,fn) {
            //.........
            //console.log("要处理的对象", objT);
            //console.log("回调函数", fn);
            if(jQuery.isArray(objT) || jQuery.isLikeArray(objT))
            {
                //for循环
                for (var i = 0; i < objT.length; i++) {
                    //key == i
                    //value objT[i];
                    var key = i;
                    var value = objT[i];

                    //第一个参数:value用来绑定给fn这个函数中的this
                    //第二个(三个)参数:key和value是传递给fn这个回调函数的
                    var result = fn.apply(value,[key,value]);
                    if(result == false) break;
                    //结束循环:
                    //break      结束整个循环
                    //continue   结束当前循环,继续执行下一次循环
                }
            }else if(jQuery.isObject(objT))
            {
                //for..in
                for(var i in objT)
                {
                    var key = i;
                    var value = objT[i];
                    if(fn.call(value,key,value) == false) break;
                }
            }
        },
        map:function (arrT,fn) {
            var arrM = [];
            if(jQuery.isArray(arrT) || jQuery.isLikeArray(arrT))
            {
                //遍历数组,处理数组,并且收集回调函数中的返回值保存为一个新的数组返回
                for(var i = 0;i<arrT.length;i++)
                {
                    var result = fn(arrT[i],i);
                    if(result){
                        arrM.push(result);
                    }
                }
            }else if(jQuery.isObject(arrT))
            {
                for(var i in arrT)
                {
                    var result = fn(arrT[i],i);
                    if(result){
                        arrM.push(result);
                    }
                }
            }

            return arrM;
        }
    })

    //常用操作DOM节点方法(jQuery原型方法)
    jQuery.fn.extend({
        attr:function () {
            //参数情况分析
            //[1] 0个参数 ||  (1)参数既不是字符串也不是对象   ==> 报错
            //[2] 1个参数
            //    001 字符串      获取指定标签(第一个)对应属性节点的值
            //    002 对象        批量设置
            //[3] 2个参数         批量的添加|修改所有指定标签对应的属性节点
            if(arguments.length == 0 || (!jQuery.isString(arguments[0]) && !jQuery.isObject(arguments[0]))){
                throw "参数不正确";
            }else if(arguments.length == 1)
            {
                if(jQuery.isString(arguments[0]))
                {
                   return this.get(0).getAttribute(arguments[0]);
                }else
                {
                    //{"xxx":"xxxx","ddd":"dddd"}
                    /*
                    for(var i in this)
                    {
                        var oDiv = this[i];
                        for(var key in arguments[0])
                        {
                            oDiv.setAttribute(key,arguments[0][key]);
                        }
                    }*/

                    var obj =arguments[0];
                    this.each(function (index,ele) {
                        $.each(obj ,function (key,value) {
                            ele.setAttribute(key,value);
                        })
                    })

                }
            }else if(arguments.length ==2)
            {
                /*
                for(var i in this)
                {
                    var oDiv = this[i];
                    oDiv.setAttribute(arguments[0],arguments[1]);
                }*/
                var p1 = arguments[0];
                var p2 = arguments[1];

                this.each(function (index,ele) {
                    ele.setAttribute(p1,p2);
                    //this.setAttribute(arguments[0],arguments[1]);
                })

            }
        },
        removeAttr:function (key) {
            if(arguments.length == 1 && jQuery.isString(key))
            //if(arguments.length == 1 && typeof key === "string")
            {
                this.each(function (index,ele) {
                    //ele当前的每一个标签
                    //this-->value -->ele
                    this.removeAttribute(key);
                })
            }
            return this;
        },
        prop:function () {

        },
        removeProp:function () {

        }
    })

    //要访问闭包中的私有变量
    //(1) 直接返回该变量(函数包装)
    //(2) 把闭包中的变量绑定给全局对象
    window.jQuery = window.$ = jQuery;
})(window)

on方法的实现分析


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>17-on方法的实现分析</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
    <!--<script src="js/jquery-2.0.0.js"></script>-->
    <script src="js/XMGQuery-1.5.1.js"></script>

</head>
<body>
<div>div1</div>
<div>div2</div>
<div>div3</div>
<script>
    //on()
    //作用:给标签批量的注册事件
    //特点:
    //[1] 添加多次,不会覆盖
    function fn(e) {
        console.log("点击了标签", e.target);
    }
    //$("div").on("click",fn)
    //$("div").off("click",fn);

    //    var oDiv = document.getElementsByTagName("div")[0];
    //    function callBack1() {
    //        console.log("点击事件1");
    //    }
    //    function callBack2() {
    //        console.log("点击事件2");
    //    }
    //    oDiv.addEventListener("click",callBack1);
    //    oDiv.addEventListener("click",callBack2);
    //
    //    oDiv.removeEventListener("click",callBack1);
    //    //oDiv.detachEvent("onclick",callBack1);

    $("div").click(function () {
        console.log("点击事件");
    })

    $("div").mouseenter(function () {
        console.log("鼠标移入事件");
    })
</script>
</body>
</html>

JQuery 设计模式

/**
 * Created by Administrator on 2018/5/27.
 */

//外层是即时函数(闭包)
(function (window,undefined) {

    //定义jQuery函数
    var jQuery = function (selector) {
        return new jQuery.prototype.init(selector);
    }

    //设置jQuery原型对象
    jQuery.fn = jQuery.prototype = {
        constructor:jQuery,
        jquery:"v 1.2.0",
        selector:"",
        length:0,
        init:function (selector) {

            //入口函数 ..
            //判断类型---> 写具体的实现

            //[00] 条件判断为假==>返回空的jQ实例对象
            //this --> 指向新创建的实例对象(jQ实例对象)
            if(!selector)
            {
                return this;
            }
            //[01] 参数是函数
            else if($.isFunction(selector))
            {
                this.ready(selector);
            }
            //[02] 参数是字符串
            //判断:是字符串 && 标签
            //==>  把传入的所有一级标签作为key为0,1,2...对应value值保存到jQ实例对象中
            else if($.isString(selector))
            {
                //容错性处理
                selector = $.trim(selector);
                //A 标签
                if($.isHtmlStr(selector)){

                    //根据参数获取所有的一级标签
                    var oDiv = document.createElement("div");
                    oDiv.innerHTML = selector;

                    //总结:遍历数组把数组中每个元素依次取出保存到this对象中,更新length
                    [].push.apply(this,oDiv.children);
                }
                //B 选择器
                else
                {
                    //根据参数获取页面中对应的标签
                    //然后把它们作为key为0,1,2...对应的value保存到jQ实例对象中返回
                    [].push.apply(this,document.querySelectorAll(selector));
                }
            }
            //[03] 参数是数组或者是伪数组
            else if($.isArray(selector) || $.isLikeArray(selector))
            {
                var arrM = [].slice.call(selector);
                [].push.apply(this,arrM);
            }
            //[04] 其它情况
            else {
                //DOM | 非0的数字 | true
                //把(selector)整体作为key为0对应的value值保存到jQ实例对象中返回
                this[0] = selector;
                this.length = 1;
            }

        },
        ready:function (fn) {

            if(document.readyState === "complete")
            {
                fn();
                return;
            }

            //监听DOM加载,调用函数
            //if(DOM加载完) selector();
            if(document.addEventListener)
            {
                document.addEventListener("DOMContentLoaded",fn);
            }else {
                document.attachEvent("onreadystatechange",function () {
                    if(document.readyState === "complete")
                    {
                        fn();
                    }
                })
            }
        },
        toArray:function () {
            //作用:把jQ实例对象 --> 数组返回
            //this
            //console.log("this",this);
            return [].slice.call(this);
        },
        get:function (index) {
            //获取this中索引为index的标签返回
            //[0] 没有参数,返回数组
            if(arguments.length === 0)
            {
                return this.toArray();
            }else if(arguments.length ===1 && typeof index === "number") {
                    //[1] 参数是正数
                if (index >= 0) {
                    return this[index];
                } else
                {
                    //[2] 参数是负数
                    //-1 倒数第一个    索引为3 == length + (-1)
                    //-2 倒数第二个    索引为2 == length + (-2)
                    //-3 倒数第三个    索引为1 == length + (-3)
                    return this[this.length + index];
                }
            }
        },
        eq:function (index) {
            if(index == undefined)
            {
                return $();
            }
            else if(arguments.length ===1 && typeof index === "number")
            {
                /*
                if (index >= 0) {
                    return $(this[index]);
                } else
                {
                    return $(this[this.length + index]);
                }*/
                return $(this.get(index));
            }
        },
        first:function () {
            return this.eq(0);
        },
        last:function () {
            return this.eq(-1)
        },
        sort: [].sort,
        splice: [].splice,
        each:function (fn) {
           jQuery.each(this,fn);
        }
    }

    //设置init的原型对象指向jQuery的原型对象
    jQuery.prototype.init.prototype = jQuery.prototype;

    //插件扩展方法
    //声明了两个方法,函数体中的this由调用上下文决定
    jQuery.fn.extend = jQuery.extend = function (obj) {
        for(var key in obj)
        {
            if(typeof obj[key] === "function" && obj.hasOwnProperty(key))
            {
                this[key] = obj[key];
            }
        }
    }

    //常用工具方法(jQuery静态方法)
    jQuery.extend({
        isWindow:function (obj) {
            return obj != null && obj == obj.window;
        },
        isObject:function (obj) {
            return typeof obj === "object" && obj != null && !this.isArray(obj)
        },
        isString:function (str) {
            return typeof str === "string"
        },
        isHtmlStr:function (htmlStr) {
            //(1) 以<开头
            //(2) 以>结尾
            //(3) 长度>=3
            return htmlStr.charAt(0) === "<" && htmlStr.charAt(htmlStr.length-1) ===">" && htmlStr.length >=3
        },
        isArray:function (arr) {
            if(Array.isArray)
            {
                return Array.isArray(arr);
            }else
            {
                return Object.prototype.toString.call(arr) === "[object Array]";
            }
        },
        isLikeArray:function (obj) {
            //(1) key从0开始依次递增(但是允许存在其他的key,在处理的时候会被忽略)
            //(2) 拥有length属性,拥有length-1键值对
            //(3) 本身是对象不是数组
            return this.isObject(obj) && "length" in obj && obj.length-1 in obj && !this.isWindow(obj)
        },
        trim:function (str) {
            if(str.trim)
            {
                return str.trim();
            }else
            {
                return str.replace(/^\s+|\s+$/g,"");
            }
        },
        isFunction:function (fn) {
            return typeof fn === "function";
        }
    });

    //each和map方法(jQuery静态方法)
    jQuery.extend({
        each:function (objT,fn) {
            //.........
            //console.log("要处理的对象", objT);
            //console.log("回调函数", fn);
            if(jQuery.isArray(objT) || jQuery.isLikeArray(objT))
            {
                //for循环
                for (var i = 0; i < objT.length; i++) {
                    //key == i
                    //value objT[i];
                    var key = i;
                    var value = objT[i];

                    //第一个参数:value用来绑定给fn这个函数中的this
                    //第二个(三个)参数:key和value是传递给fn这个回调函数的
                    var result = fn.apply(value,[key,value]);
                    if(result == false) break;
                    //结束循环:
                    //break      结束整个循环
                    //continue   结束当前循环,继续执行下一次循环
                }
            }else if(jQuery.isObject(objT))
            {
                //for..in
                for(var i in objT)
                {
                    var key = i;
                    var value = objT[i];
                    if(fn.call(value,key,value) == false) break;
                }
            }
        },
        map:function (arrT,fn) {
            var arrM = [];
            if(jQuery.isArray(arrT) || jQuery.isLikeArray(arrT))
            {
                //遍历数组,处理数组,并且收集回调函数中的返回值保存为一个新的数组返回
                for(var i = 0;i<arrT.length;i++)
                {
                    var result = fn(arrT[i],i);
                    if(result){
                        arrM.push(result);
                    }
                }
            }else if(jQuery.isObject(arrT))
            {
                for(var i in arrT)
                {
                    var result = fn(arrT[i],i);
                    if(result){
                        arrM.push(result);
                    }
                }
            }

            return arrM;
        }
    })

    //常用操作DOM节点方法(jQuery原型方法)
    jQuery.fn.extend({
        attr:function () {
            //参数情况分析
            //[1] 0个参数 ||  (1)参数既不是字符串也不是对象   ==> 报错
            //[2] 1个参数
            //    001 字符串      获取指定标签(第一个)对应属性节点的值
            //    002 对象        批量设置
            //[3] 2个参数         批量的添加|修改所有指定标签对应的属性节点
            if(arguments.length == 0 || (!jQuery.isString(arguments[0]) && !jQuery.isObject(arguments[0]))){
                throw "参数不正确";
            }else if(arguments.length == 1)
            {
                if(jQuery.isString(arguments[0]))
                {
                   return this.get(0).getAttribute(arguments[0]);
                }else
                {
                    //{"xxx":"xxxx","ddd":"dddd"}
                    /*
                    for(var i in this)
                    {
                        var oDiv = this[i];
                        for(var key in arguments[0])
                        {
                            oDiv.setAttribute(key,arguments[0][key]);
                        }
                    }*/

                    var obj =arguments[0];
                    this.each(function (index,ele) {
                        $.each(obj ,function (key,value) {
                            ele.setAttribute(key,value);
                        })
                    })

                }
            }else if(arguments.length ==2)
            {
                /*
                for(var i in this)
                {
                    var oDiv = this[i];
                    oDiv.setAttribute(arguments[0],arguments[1]);
                }*/
                var p1 = arguments[0];
                var p2 = arguments[1];

                this.each(function (index,ele) {
                    ele.setAttribute(p1,p2);
                    //this.setAttribute(arguments[0],arguments[1]);
                })

            }
        },
        removeAttr:function (key) {
            if(arguments.length == 1 && jQuery.isString(key))
            //if(arguments.length == 1 && typeof key === "string")
            {
                this.each(function (index,ele) {
                    //ele当前的每一个标签
                    //this-->value -->ele
                    this.removeAttribute(key);
                })
            }
            return this;
        },
        prop : function (){
            if(arguments.length == 0|| (!jQuery.isString(arguments[0]) && !jQuery.isObject(arguments[0]))){
                throw '��������ȷ';
            }else if(arguments.length == 1){
                if(jQuery.isString(arguments[0])){
                    //$().prop("a") return div1["a"]
                    return this.get(0)[arguments[0]];
                }else {
                    var obj = arguments[0];
                    this.each(function(index,ele){
                        $.each(obj,function(key,value){
                            ele[key] = value;
                        })
                    })
                }
            }else if(arguments.length == 2){
                var p1 = arguments[0];
                var p2 = arguments[1];

                this.each(function(index,ele){
                    ele[p1] = p2;
                })
            }
        },
        removeProp: function(key){
            if(arguments.length == 1 && jQuery.isString(key)){
                this.each(function(index,ele){
                    delete ele[key];
                })
            }
            return this;
        },
        val:function (valueT) {
            if(arguments.length == 0)
            {
                return this.get(0)["value"];
            }else
            {
                this.each(function (index,ele) {
                    //ele 就是当前操作的标签
                    ele["value"] = valueT;
                })
            }
            return this;
        },
        html:function (htmlContent) {

            if(arguments.length == 0){
               return this.get(0).innerHTML;
            }else {
                //思路:
                //(1) 先对参数进行判断
                //A 没有参数
                //B 有一个参数  批量设置
                //(2) 具体的代码实现
                /*
                for(var key in htmlContent){

                    this[key].innerHTML = htmlContent;
                }*/
                this.each(function () {
                    //this是当前正在操作的标签  div
                    //console.log(this);
                    this.innerHTML = htmlContent;
                })
                return this
            }
        },
        text:function (textContent) {
            // if(!jQuery.isString(textContent)){
            //     throw '错误';
            // }

            if(arguments.length == 0) {
                var temp = '';
                this.each(function () {
                    temp = temp + this.innerText;
                })
                return temp;

            }else if(arguments.length == 1){
                this.each(function () {
                    this.innerText = textContent;
                })
            }

            /*
            var temp = '';
            this.each(function () {
                textContent ? (this.innerText = textContent):(temp += this.innerText);
            });*/
            return this;
        },
        empty:function () {
            //遍历当前的jQ实例对象,把所有标签的内容都清除
            $.each(this,function (index,ele) {
                //ele 当前的标签  == this
                ele.innerHTML = "";
            })
            return this;
        },
        remove:function () {
            //遍历jQ实例对象,获取当前的每一个标签,依次删除
            $.each(this,function (index,ele) {
                //ele 当前的标签
                /*
                var node = ele.parentNode;
                node.removeChild(ele);*/
                this.parentNode.removeChild(this);
            })
            return this;
        },
        appendTo:function (target) {
            // var oDivs  = document.querySelectorAll("div");
            // var oLis = document.querySelectorAll("li");
            // for(var i = 0;i<oLis.length;i++)
            // {
            //     var oli = oLis[i];
            //     for(var j = 0 ;j<oDivs.length;j++)
            //     {
            //         var oDiv = oDivs[j];
            //         var temp ;
            //
            //         if(j == 0)
            //         {
            //             temp = oli;
            //         }else
            //         {
            //             temp = oli.cloneNode(true);
            //         }
            //         oDiv.appendChild(temp);
            //     }
            // }
            var arrM = [];
            if(jQuery.isString(target))
            {
                target = $(target);
            }

            //oDivs === target
            //oLis  === this
            this.each(function (index,ele) {
                //index === i
                //ele   === oli
                $.each(target,function (_index,_ele) {
                    //_index === j
                    //_ele   === oDiv
                    var temp ;
                    if(_index == 0)
                    {
                        temp = ele;
                    }else
                    {
                        temp = ele.cloneNode(true);
                    }
                    _ele.appendChild(temp);
                    arrM.push(temp);
                })
            })
            return $(arrM);
        },
        append:function (target) {
            //console.log($("div").append($("li")));  //== console.log($("li").appendTo("div"));
            //$("div")  == this
            //$("li")   == target
            if(jQuery.isObject(target))
            {
                return target.appendTo(this);
            }else
            {
                this.each(function () {
                    this.innerHTML += target;
                })
            }


        },
        prependTo:function (target) {
            var arrM = [];
            if(jQuery.isString(target))
            {
                target = $(target);
            }

            // this.each(function (index,ele) {
            //     //index === i
            //     //ele   === oli
            //     $.each(target,function (_index,_ele) {
            //         //_index === j
            //         //_ele   === oDiv
            //         var temp ;
            //         if(_index == 0)
            //         {
            //             temp = ele;
            //         }else
            //         {
            //             temp = ele.cloneNode(true);
            //         }
            //
            //         //_ele.appendChild(temp);  把temp标签插入到_ele标签内容的后面
            //         //_ele.prependChild(X)     把temp标签插入到_ele标签内容的前面
            //         _ele.insertBefore(temp,_ele.firstChild);
            //         arrM.push(temp);
            //     })
            // })
            var self = this;
            $.each(target,function (_index,_ele) {
                var node = _ele.firstChild;
                self.each(function (index,ele) {
                    var temp ;
                    if(_index == 0)
                    {
                        temp = ele;
                    }else
                    {
                        temp = ele.cloneNode(true);
                    }
                    //_ele.appendChild(temp);  把temp标签插入到_ele标签内容的后面
                    //_ele.prependChild(X)     把temp标签插入到_ele标签内容的前面
                    _ele.insertBefore(temp,node);
                    arrM.push(temp);
                })
            })
            return $(arrM);
        },
        prepend:function (target) {
            //console.log($("div").append($("li")));  //== console.log($("li").appendTo("div"));
            //$("div")  == this
            //$("li")   == target
            if(jQuery.isObject(target))
            {
                return target.prependTo(this);
            }else
            {
                this.each(function () {
                    this.innerHTML = target + this.innerHTML ;
                })
            }


        }
    })

    //常用操作CSS的方法(jQuery原型方法)
    jQuery.fn.extend({
        css:function () {
            if(arguments.length == 0 || (!jQuery.isString(arguments[0]) && !jQuery.isObject(arguments[0]))){
                throw "参数不正确";
            }else if(arguments.length == 1)
            {
                //1个参数:字符串
                //console.log($("div").css("width"));
                if(jQuery.isString(arguments[0]))
                {
                   var key = arguments[0];
                   var temp =  this.get(0);
                   if(window.getComputedStyle)
                   {
                       return window.getComputedStyle(temp)[key];
                   }else
                   {
                       return temp.currentStyle[key];
                   }
                }else
                {
                    //1个参数:对象
                    //遍历jQ对象,拿到每一个标签设置样式
                    //遍历传入的参数对象,获取每一个键值对设置样式
                    var objT = arguments[0];
                    this.each(function () {
                        var self = this;
                        $.each(objT,function (key,value) {
                            self.style[key] = value;
                        })
                    })
                }
            }else if(arguments.length ==2)
            {
                //2个参数
                //$("div").css("background","green");
                //遍历jQ对象,拿到每一个标签设置样式
                var key = arguments[0];
                var value = arguments[1];
                this.each(function () {
                    this.style[key] = value;
                })
            }
        },
        hasClass:function (className) {
            //if(没有参数) 返回false
            //else (有参数) 遍历jQ实例对象,拿到每一个标签,检查当前标签中是否存在指定的样式(class),如果有那么就返回true,并且结束循环.如果没有找到,重复这个过程,直到找到为止或者循环结束,如果循环结束都没有匹配到那么就返回false
            var flag = false;
            if(className){
                this.each(function () {
                    //this --> value 当前的标签
                    //className 传入的参数  "testB"
                    //this.getAttribute("class") div-class testA
                    var classT = " " + this.getAttribute("class") + " ";
                    if(classT.indexOf(" " + className + " ") != -1)
                    {
                        //[1] 返回true
                        flag = true;
                        //[2] 终止循环
                        return false;
                    }

                })
            }
            return flag;
        },
        addClass:function (className) {
            //"testA"
            //"testA testB testC"
            //遍历jQ实例对象,获取每一个标签,添加class
            this.each(function () {
                var arrM = className.split(" ");
                //["testA", "testB", "testC"]
                var self = this; //当前的标签(DOM)
                $.each(arrM,function (index,classT) {
                    //index 0,1,2,3,..
                    //classT testA testB testC
                    //检查当前的标签上是否存在指定的class,如果不存在那么就添加
                    if(!$(self).hasClass(classT))
                    {
                        //self.setAttribute("class",self.getAttribute("class") + " " + classT);
                        self.className += " " + classT;
                    }
                })
            })

            return this;
        },
        removeClass:function (className) {
            if(arguments.length == 0)
            {
                this.each(function () {
                    this.className = "";
                })
            }else
            {
                var arrM = className.split(" ");
                //$("div").removeClass("testB testA");
                //["testA","testB"];
                this.each(function () {
                    var self = this;
                    $.each(arrM,function (index,classT) {
                        if($(self).hasClass(classT))
                        {
                            //self.className  div-class testA testB
                            //classT          testA
                            //self.className  div-class testB
                            var str1 = " " + self.className + " ";
                            var str2 = " " + classT + " ";
                            self.className = jQuery.trim(str1.replace(str2," "));
                        }
                    })
                })
            }

            return this;
        },
        toggleClass:function (className) {
            if(className == undefined)
            {
                this.removeClass();
            }else
            {
                //$("div").toggleClass("A B testA");
                //className "A B testA"
                var arrM = className.split(" ");
                this.each(function () {
                    var self = this;
                    $.each(arrM,function (index,classT) {
                        if($(self).hasClass(classT))
                        {
                            $(self).removeClass(classT);
                        }else
                        {
                            $(self).addClass(classT);
                        }
                    })
                })
            }

            return this;
        }
    })

    //常用事件处理相关的方法(jQuery原型方法)
    jQuery.fn.extend({
        on:function (type,fn) {
            //遍历jQ实例对象,拿到每个标签,给标签绑定事件并设置事件处理函数
            this.each(function () {
                if(this.addEventListener)
                {
                    this.addEventListener(type,fn);
                }else
                {
                    this.attachEvent("on"+type,fn);
                }
            })
        },
        off:function (type,fn) {
            this.each(function () {
                if(this.removeEventListener)
                {
                    this.removeEventListener(type,fn);
                }else
                {
                    this.detachEvent("on"+type,fn);
                }
            })
        },
        click:function (fn) {
            this.on("click",fn);
        },
        mouseenter:function (fn) {
            this.on("mouseenter",fn)
        }
    })

    //要访问闭包中的私有变量
    //(1) 直接返回该变量(函数包装)
    //(2) 把闭包中的变量绑定给全局对象
    window.jQuery = window.$ = jQuery;

})(window)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

web修理工

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值