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

news/2024/11/9 13:12:27

简化版自己实现jQuery

1. == 与===

尽量不要用 == 规则太复杂
ChUuAf.png

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

2.自己写jQuery与用jQuery

Ch7FXj.png

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>jQuery-Study</title>
    <script src="01_myjQuery1.js"></script>
    <script src="jQuery3.3.1min.js"></script>
    <style>
        .red{
            color: red;
        }
        .blue{
            color: blue;
        }
        .big{
            font-size: larger;
        }
        .green{
            color: green;
        }
        .pink{
            color: pink;
        }
    </style>
</head>
<body>
<!--ul>li[id=item$]{这是li$}*8-->
<ul>
    <li id="item1">这是li1</li>
    <li id="item2">这是li2</li>
    <li id="item3">这是li3</li>
    <li id="item4" class="xxx">这是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/

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

ChN7kT.png
dom就是一个命名的空间,命名的所属对象
函数库:特定种类的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>

结果如下:
CXIos1.png

CXo8W4.png
就像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')



http://www.niftyadmin.cn/n/1901381.html

相关文章

Vulkan规范:第九章 9.7

9.7. 特化常量&#xff08;Specialization Constants&#xff09; 特化常量是一种机制&#xff0c;在SPIR-V模块中保有VkPipeline被创建时指定的常量。 这允许SPIR-V模块保有应用程序运行过程中通过Vulkan API可更改的常量。 注意计算着色器需要在运行时改变本地工作组大小时&a…

惠普战66怎么用u盘进入系统_体验惠普战66二代商务本:升级MX250,办公大有竞争力!...

2016年12月&#xff0c;惠普针对中小企业用户推出首款战系列笔记本电脑。时间来到2019年&#xff0c;随着英特尔第八代酷睿处理器(Whiskey Lake平台)的更新&#xff0c;惠普也对旗下战系列产品线进行了升级&#xff0c;推出了全新的战66二代笔记本(具体型号为惠普战66 Pro 14 G…

关于前端开发的资源推荐与总结【持续更新】

我们很多人总会有这样一个问题&#xff0c;就是喜欢收藏很多东西&#xff0c;自我安慰说等有时间了一定好好看&#xff0c;以至于网页收藏夹、微信收藏栏、百度网盘等处积累了太多资源&#xff0c;给人一种学富五车的样子&#xff0c;而只有自己才知道&#xff0c;被收藏的东西…

计算几何实践1:基础

2017-11-27计算几何在CAD开发&#xff0c;游戏开发中比较重要&#xff0c;可能只有机械和CAD方向的研究生才把这门课作为基础课程&#xff0c;很多做游戏的同学未必专门学习过这门课程。我觉得专门学习一下还是非常有必要的。我这两年多基本上在做CAD的开发&#xff0c;或多或少…

imageview设置在最顶层_最全面 Mybatis 框架核心配置文件使用总结,值得收藏

前言今天本篇主要介绍一下MyBatis的全局配置文件的使用。configurationmybatis-config.xml文件的头部格式我们就不说了&#xff0c;直接从属性开始介绍&#xff0c;configuration为最顶层节点&#xff0c;其余所有的属性都必须嵌套在configuration内,MyBatis配置文件的顶层节点…

改变maven仓库位置_maven修改远程和本地仓库地址

简介&#xff1a;我们用maven的时候&#xff0c;maven自带的远程中央仓库经常会很慢&#xff0c;还有默认本地仓库是在c盘C:\Users\你的电脑用户账号\.m2\repository&#xff0c;对于有强迫症的人&#xff0c;总是看的不爽&#xff0c;下面介绍下经验&#xff1a;我的环境&…

6 频率_做自动化这么多年,你知道6类线与5类线的区别吗?

为什么6类线比5类线的传输速率快&#xff1f;我们平时使用的最多的就是网线&#xff0c;关于网线的各种属于却很少了解&#xff0c;做很多项目时&#xff0c;我们都有个错觉&#xff0c;觉得5类线与6类线区别不大&#xff0c;今天我们来看下&#xff0c;6类线与5类线的区别在哪…

用H5+Boostrap做简单的音乐播放器

前言&#xff1a;这个是综合一下我最近在学的东西做的小Demo&#xff0c;到实际使用还有距离&#xff0c;但是用来练手巩固知识点还是不错的&#xff0c;最近在二刷JS书和Boostrap.css的源码&#xff0c;做完这个Demo也算是暂告一段落&#xff0c;接下来是jQuery的源码和Boostr…