美文网首页
简化版自己实现jQuery及this、arguments、闭包、

简化版自己实现jQuery及this、arguments、闭包、

作者: 如梦初醒Tel | 来源:发表于2019-05-22 17:07 被阅读0次

    简化版自己实现jQuery

    == 与===

    参考博文为什么推荐使用 === 不推荐 ==
    尽量不要用 == 规则太复杂

    image.png

    用===只需要注意两点,1.NaN===NaN,false,2.所有对象===也都是false,因为地址不一样.

    image.png

    自己写jQuery与用jQuery

    mydemo预览
    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title><!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <title>jQuery-Study</title>
                <script src="01_myjQuery1.js"></script>
                <script src="https://code.jquery.com/jquery-3.1.0.js"></script>
                <style>
                    .red {
                        color: red;
                    }
    
                    .blue {
                        color: blue;
                    }
    
                    .big {
                        font-size: larger;
                    }
    
                    .green {
                        color: green;
                    }
    
                    .pink {
                        color: pink;
                    }
                    .yellow{
                        color: yellow;
                    }
                </style>
            </head>
    <body>
    
    <ul>
        <li id="item1">这是li1</li>
        <li id="item2">这是li2</li>
        <li id="item3">这是li3</li>
        <li id="item4">这是li4</li>
        <li id="item5">这是li5</li>
        <li id="item6">这是li6</li>
        <li id="item7">这是li7</li>
        <li id="item8">这是li8</li>
    </ul>
    
    <button id="x">x</button>
    <ol id="ol2">
        <li id="i1">1</li>
        <li id="i2">2</li>
        <li id="i3">3</li>
        <li id="i4">4</li>
        <li id="i5">5</li>
    </ol>
    </body>
    <script>
        console.log('直接使用');
        console.log(getSiblings(item1));
    
        console.log('直接使用');
        addClass(item2,{a:true,xxx:false,c:true});
        console.log(item2);
    </script>
    <script src="UseJquery.js"></script>
    </html>
    

    01_myjQuery1.js

    // 得到兄妹结点
    //传入的参数是一个节点,返回兄妹结点的数组
    function getSiblings(node) {
        var allSilings = node.parentNode.children;
        var siblingsArray = {length:0};
        for (let i = 0; i < allSilings.length; i++) {
            if (allSilings[i]!==node){
                siblingsArray[siblingsArray.length] = allSilings[i];
                siblingsArray.length++;
            }
        }
        return siblingsArray;
    }
    //添加或删除class
    //传入的第一个参数是结点,第二个参数是对象, 这个对象里是key:value,key就是要操作的class,value判断操作类型,true添加,false删除
    function addClass(node,object){
        for (let key in object){
            //对象调用方法的两种方式:
            // obj.f()
            // obj['f']()
    
            var methodName;
    
            methodName = object[key] ? 'add':'remove';
            node.classList[methodName](key);
    
            /*上面两句代码相当于
            if (object[key]) {
                node.classList.add(key);
            }else {
                node.classList.remove(key);
            }*/
        }
    }
    window.mydom = {};
    mydom.getSiblings = getSiblings;
    mydom.addClass = addClass;//命名空间,常用的设计或者组合就叫做设计模式.哈希,数组,都是一种设计模式
    //所以jQuery就是这样来的,jQuery就是一个命名空间,里面有很多函数.
    
    // 命名空间作用:1.方便识别库,2.如果都放在window里,可能会覆盖别的库,所以命名空间是为了防止覆盖别的函数
    
    window.onload = function () {
    // 测试
    
    
        // 如何直接使用item3.addclass()?,item3.getSiblings()?
        // 方法一:给原型链加公有属性公有方法,但是有缺点,容易覆盖
        Node.prototype.getSiblings = function () {
            var allSilings = this.parentNode.children;//谁调用这个函数,this就是谁
            var siblingsArray = {length:0};
            for (let i = 0; i < allSilings.length; i++) {
                if (allSilings[i]!==this){
                    siblingsArray[siblingsArray.length] = allSilings[i];
                    siblingsArray.length++;
                }
            }
            return siblingsArray;
        }
        let item3 = document.getElementById('item3');
        // console.log(item3.getSiblings.call(item3));如果用cal.第一个参数就是函数里的this,如果不用call(),那么this就自动变成了item3
        console.log(' 方法一:');
        console.log(item3.getSiblings());//测试成功
    
        Node.prototype.addClass = function (object) {
            for (let key in object){
                var methodName;
                methodName = object[key] ? 'add':'remove';
                this.classList[methodName](key);
            }
        }
        // item3.addClass.call(item3,{a:true,xxx:false,c:true});;如果用call.第一个参数就是函数里的this,如果不用call(),那么this就自动变成了item3
        console.log(' 方法一:');
        item3.addClass.call(item3,{a:true,xxx:false,c:true});
        // item3.addClass({a:true,xxx:false,c:true});
        console.log(item3);//测试成功
    
    
        // 如何直接使用item3.addclass()?,item3.getSiblings()?
        // 方法二:因为方法一在原型中添加函数容易覆盖,所以自己做一个类似的Node出来
        var Node2 = function (node) {// 将要操作的结点传进去,然后返回一个对象,这个对象里给添加了有操作这个节点方法,所以对象.方法就可以实现操作了,而不需要mydom.addclass(item3,...)这样了
            return{
                getSiblings: function () {
                    var allSilings = node.parentNode.children;
                    var siblingsArray = {length:0};
                    for (let i = 0; i < allSilings.length; i++) {
                        if (allSilings[i]!==node){
                            siblingsArray[siblingsArray.length] = allSilings[i];
                            siblingsArray.length++;
                        }
                    }
                    return siblingsArray;
                },
                addClass:function (object) {
                    for (let key in object){
    
                        var methodName;
    
                        methodName = object[key] ? 'add':'remove';
                        node.classList[methodName](key);
    
                    }
                }
            }
        }
        let item4 = document.getElementById('item4');
    
        var item4obj = Node2(item4);
    
        console.log(' 方法二:');
        console.log(item4obj.getSiblings());//测试成功
    
        console.log(' 方法二:');
        item4obj.addClass({a:true,xxx:false,c:true});
        console.log(item4);//测试成功
    
        // 改为jQuery
        var jQuery = function (nodeOrSelector) {//将Node2改为jQuery,jQuery可以根据选择器去找到对应的元素
            var node;
            if(typeof nodeOrSelector==="string"){
                node = document.querySelector(nodeOrSelector);
            }else {
                node = nodeOrSelector;
            }
            return{
                getSiblings: function () {
                    var allSilings = node.parentNode.children;
                    var siblingsArray = {length:0};
                    for (let i = 0; i < allSilings.length; i++) {
                        if (allSilings[i]!==node){
                            siblingsArray[siblingsArray.length] = allSilings[i];
                            siblingsArray.length++;
                        }
                    }
                    return siblingsArray;
                },
                addClass:function (object) {
                    for (let key in object){
    
                        var methodName;
    
                        methodName = object[key] ? 'add':'remove';
                        node.classList[methodName](key);
    
                    }
                }
            }
        }
        let item5 = document.getElementById('item5');
    
        var $item5 = jQuery(item5);
        console.log(' 改为jQuery方法:');
        console.log($item5.getSiblings());
    
        console.log(' 改为jQuery方法:');
        $item5.addClass({red:true,xxx:false,c:true});
        console.log(item5);//测试成功
        var child3 = jQuery('ul>li:nth-child(3)');
        child3.addClass({blue:true});
    
    
        // jQuery操作多个节点
        var jQueryS = function (nodeOrSelector) {
            var node = {};
            if (typeof nodeOrSelector ==='string'){
                var temp = document.querySelectorAll(nodeOrSelector);//先用querySelectorAll获取这个伪数组
                for (let i = 0; i < temp.length; i++) {
                    node[i] = temp[i];
                }
                node.length = temp.length;//将伪数组净化,净化成只有0123值和length的伪数组
    
            } else if(nodeOrSelector instanceof Node){// 如果是node,也将其转化成伪数组
                node[0] =nodeOrSelector;
                node.length = 1;
            }
            node.getSiblings = function () {
    
            };
            node.addClass = function (classesArray) {//传入class数组,给选择的多个节点都加上数组中class
                classesArray.forEach(value=>{
                    for (let i = 0; i < node.length; i++) {
                        node[i].classList.add(value);
                    }
                })
            }
            node.getTexts = function () {
                var texts=[];
                for (let i = 0; i < node.length; i++) {
                    texts.push(node[i].textContent);
                }
                return texts;
            }
            node.setTexts = function (text) {
                for (let i = 0; i < node.length; i++) {
                    node[i].textContent = text;
                }
            }
    
            //set和get合并
            node.text = function (text) {
                if (text===undefined){
                    var texts=[];
                    for (let i = 0; i < node.length; i++) {
                        texts.push(node[i].textContent);
                    }
                    return texts;
                }else{
                    for (let i = 0; i < node.length; i++) {
                        node[i].textContent = text;
                    }
                }
            }
            return node;
        }
    
        var allNodes = jQueryS('ul>li:nth-child(even)');//偶数孩子
        allNodes.addClass(['big','green']);
        console.log(allNodes.getTexts());
        console.log(allNodes.text());
        // console.log(allNodes.text(1));//测试成功
    
        //总结:jQuery的作用就是将选择其选择的元素放到一个对象里,这个对象里有01234标序,代表每一个选择的元素,有length代表所有元素加起来总共的长度,有各种方法,addclass,gettext等等.就是反悔了这样一个hash
    };
    
    

    UseJquery.js

    var $nodes  = $('ul>li:nth-child(even)');//注意$nodesjQuery声明的变量前面要加一个$,防止混淆,因为jQuery声明的变量只能用jQuery的api,不能用dom的api.
    console.log($nodes);
    x.onclick = function () {
        $nodes.toggleClass('pink');//toggle,开关,切换
        // console.log(1);
    }
    
    var colorArray = ['blue','yellow','red','pink','big']
    var $nodes2 = $('#ol2>li');
    $nodes2.addClass(function (index,currentClass) {
        return colorArray[index];//ol里面的每一个li加了'blue','yellow','red','pink','big'这几个属性
    })
    //https://www.jquery123.com/addClass/
    
    

    this 和 arguments

    f.call(asThis, input1,input2)

    其中 asThis 会被当做 this[input1,input2] 会被当做 arguments
    禁止使用 f(input1, input2),因为学会 .call 才能理解 this

    this 和 arguments

    function f(){
        'use strict'
        console.log(this)
        console.log(arguments)
        return undefined
    }
    f.call(1,2,3) // this 为 1,arguments 为 [2,3]
    

    this 的值到底是什么?一次说清楚---方应杭
    this定义:this是call的第一个参数.
    this定义:this是call的第一个参数.
    this定义:this是call的第一个参数.
    「每日一题」JS中的闭包是什么?---方应杭

    关于原型链:
    「每日一题」什么是 JS原型链?---方应杭

    JavaScript 世界万物诞生记

    image.png

    dom就是一个命名的空间,命名的所属对象
    命名空间作用:1.方便识别库,2.如果都放在window里,可能会覆盖别的库,所以命名空间是为了防止覆盖别的函数

    函数库:特定种类的API
    jQueryMobil已经过时,不要学

    jQuery的原型
    测试代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js"></script>
        <script>
            console.log($.prototype)
            console.log($.prototype.__proto__)
            console.log($.prototype.__proto__ === Object.prototype)//继承自Object
        </script>
    </head>
    <body>
        
    </body>
    </html>
    
    image.png image.png

    Jquery的原型继承自 Object

    image.png image.png

    自己实现JQuery例子

    window.jQuery = function(nodeOrSelector) {
      let nodes = {};
      if (typeof nodeOrSelector === 'string') {
        let temp = document.querySelectorAll(nodeOrSelector)
        for (let i = 0; i < temp.length; i++) {
          nodes[i] = temp[i]
        }
        nodes.length = temp.length
      } else if (nodeOrSelector instanceof Node) {
        nodes = {
          0: nodeOrSelector,
          length: 1
        }
      }
    
      nodes.addClass = function(...classes) {
        classes.forEach(value=>{
          for(let i=0;i<nodes.length;i++){
            nodes[i].classList.add(value)
          }
        })
      }
      nodes.getText = function(){
        var texts = []
        for(let i=0;i<nodes.length;i++){
          texts.push(nodes[i].textContent)
        }
        return texts;
      }
      nodes.setText = function(text){
        for(let i=0;i<nodes.length;i++){
          nodes[i].textContent = text
        }
      }
      nodes.text = function(text){
        console.log(this)
        if(text){
          this.setText(text)
        }else{
          return this.getText();
        }
      }
    
      return nodes;
    }
    
    window.$  = jQuery
    
    var $div = $('div')
    $div.addClass('red')
    $div.setText('hi') 
    
    

    相关文章

      网友评论

          本文标题:简化版自己实现jQuery及this、arguments、闭包、

          本文链接:https://www.haomeiwen.com/subject/jaruzqtx.html