资讯专栏INFORMATION COLUMN

简化版自己实现jQuery、this、arguments、闭包、原型链

Aldous / 1303人阅读

摘要:简化版自己实现与尽量不要用规则太复杂用只需要注意两点所有对象也都是因为地址不一样自己写与用这是这是这是这是这是这是这是这是这是直接使用直接使用得到兄妹结点传入的参数是一个节点返回兄妹结点的数组添加或删除传入的第一个参数是结点第

简化版自己实现jQuery 1. == 与===

尽量不要用 == 规则太复杂

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

2.自己写jQuery与用jQuery




    
    jQuery-Study
    
    
    



  • 这是li1
  • 这是li2
  • 这是li3
  • 这是li4
  • 这是li5
  • 这是li6
  • 这是li7
  • 这是li8
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5

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/
3.thisarguments
f.call(asThis, input1,input2)

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

thisarguments

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 世界万物诞生记


dom就是一个命名的空间,命名的所属对象
函数库:特定种类的API
jQueryMobil已经过时,不要学

jQuery的原型

测试代码




    
    
    
    Document
    
    


    

结果如下:


就像Boolea,Array一样,
他的原型就是jQuery.prototype

总结:自己实现jquery例子
var myjQueryS = function(node){
    var Node = {}
    Node.length = 0
    if((typeof node)==="string"){
        var nodearr  = document.querySelectorAll(node)
        for (let index = 0; index < nodearr.length; index++) {
            let element = nodearr[index];
            Node[index] = element
            Node.length++
        }
    }else{
        Node["0"] = node
        Node.length++
    }
    Node.addClass = function(addclass){
        for (let index = 0; index < Node.length; index++) {
            let element = Node[index]
            element.classList.add(addclass)
        }
    }
    Node.text = function(text){
        
        if(text===undefined){
            let textArr = []
            for (let index = 0; index < Node.length; index++) {
                let element = Node[index]
                textArr.push(element.textContent)
            }
            return textArr
        }else{
            for (let index = 0; index < Node.length; index++) {
                let element = Node[index]
                element.textContent = text
            }
        }
    }
    return Node
}
var $div = myjQueryS("div")
console.log($div)
$div.addClass("xxx")
console.log($div.text())
// $div.text("xxx")


文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95317.html

相关文章

  • JavaScript学习之路 — 函数、闭包原型

    摘要:全局的函数第个对象第个对象作为构造器进行调用也就是利用运算符进行调用。与操作的共同使用只有通过操作产生的对象,可以使用构造器函数原型链上的内容,否则对象只能使用自己原型链上的内容。 今天这个话题是因为这几天看了《JavaScript忍者秘籍》,感觉这本书把这几个内容讲的蛮透彻了,特撰本文,以便日后翻阅。(应该都会以知识点的形式给出吧。) 函数 1.【基本类型】 JavaScript中函...

    klivitamJ 评论0 收藏0
  • 【进阶 6-2 期】深入高阶函数应用之柯里化

    摘要:引言上一节介绍了高阶函数的定义,并结合实例说明了使用高阶函数和不使用高阶函数的情况。我们期望函数输出,但是实际上调用柯里化函数时,所以调用时就已经执行并输出了,而不是理想中的返回闭包函数,所以后续调用将会报错。引言 上一节介绍了高阶函数的定义,并结合实例说明了使用高阶函数和不使用高阶函数的情况。后面几部分将结合实际应用场景介绍高阶函数的应用,本节先来聊聊函数柯里化,通过介绍其定义、比较常见的...

    stackvoid 评论0 收藏0
  • JS语言缺陷

    摘要:语言缺陷是一门在极短时间里创造的脚本语言,它存在很多的不足,这使得在学习时无形加大了学习的难度,本文就将这些内容进行总结,以防继续掉坑。 JS语言缺陷 js是一门在极短时间里创造的脚本语言,它存在很多的不足,这使得在学习时无形加大了学习的难度,本文就将这些内容进行总结,以防继续掉坑。 1.变量提升 1.1 案例分析 先来说一下变量提升,它其实就是先用后声明,经常被拿来说明的一个例子是:...

    I_Am 评论0 收藏0
  • 漫谈javascript函数式编程

    摘要:高阶函数不是的所特有的,其他编程语言也有。高阶函数面向切面编程面向切面编程这种思想在开发中比较常见,主要就是将一些与核心业务无关的功能抽离出来,比如异常处理,日志统计等。 javascript的函数式语言特性 我们知道JavaScript使一门面向对象的编程语言,但这门语言同时拥有很多函数式语言的特性。 JavaScript的设计者在设计最初就参考了LISP方言之一的Scheme,引入...

    liaorio 评论0 收藏0
  • jquery里面val函数重载的实现思路

    摘要:后续说完上面的再对比下面的理解,会更深入的理解原型与原型链这里是对象拥有了这样的方法,而不是,是继承区别于方法直接作用于原型上例子的实现 所谓重载,就是一组相同的函数名,有不同个数的参数,在使用时调用一个函数名,传入不同参数,根据你的参数个数,来决定使用不同的函数!但是我们知道js中是没有重载的,因为后定义的函数会覆盖前面的同名函数,但是我们又想实现函数重载该怎么办呢? 第1种方法: ...

    learn_shifeng 评论0 收藏0

发表评论

0条评论

Aldous

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<