JavaScript之实现jQuery

术语
链式风格

也叫jQuery风格

特殊函数jQuery
  1. jQuery(选择器)用于获取对应元素
  2. 但它不返回这些元素
  3. 它返回一个对象,称之为jQuery构造出来的对象
  4. 这个对象可以操作对应的元素
一些理解
  1. jQuery是构造函数,因为它构造出来一个对象
  2. jQuery不是构造函数,因为它不需要通过new jQuery()构造一个对象
  3. 总结:jQuery是一个不需要加new的构造函数
  4. jQuery不是常规意义上的构造函数
  5. jQuery用了一些技巧

最后推荐一篇不错的博客

jQuery 都过时了,那我还学它干嘛?

实现jQuery示例

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>实现jQuery示例</title>
    </head>
    <body>
        <div class="test">
            你好1
            <div class="child">child1</div>
            <div class="child">child2</div>
            <div class="child">child3</div>
        </div>
        <div class="test">
            你好2
            <div class="child">child4</div>
            <div class="child">child5</div>
        </div>
        <div class="test">
            你好3
            <div class="child">child6</div>
        </div>
        <div id="container">
            container
        </div>
        <script src="jquery.js"></script>
        <script src="main.js"></script>
    </body>
</html>
//这种写法代码不够优化,原因:当你创建多个jQuery对象的时候,对象的共有属性是不共有的,占用内存
window.$ = window.jQuery = (selectorOrArrayOrTemplate) => {
    let elements;
    if(typeof selectorOrArrayOrTemplate === "string"){
       if(selectorOrArrayOrTemplate[0] === "<"){
            elements = [createElement(selectorOrArrayOrTemplate)];
       }else{
            elements = document.querySelectorAll(selectorOrArrayOrTemplate);
       }
    }else if(selectorOrArrayOrTemplate instanceof Array){
        elements = selectorOrArrayOrTemplate;
    }

    function createElement (String){
        const container = document.createElement("template");
        container.innerHTML = string.trim();
        return container.content.firstChild;
    }
   //返回本身,可以操作elements
   return {
        jquery: true,
        elements: elements,
        get (index) {
            return elements[index];
        },
        appendTo (node) {
            if( node instanceof Element){
                // 遍历 elements,对每个 el 进行 node.appendChild 操作
                this.each(el => node.appendChild(el));
            }else if(node.jquery === true){
                // 遍历 elements,对每个 el 进行 node.get(0).appendChild(el))  操作
                this.each(el => node.get(0).appendChild(el))
            }
        },
        append (children) {
            if(children instanceof Element){
                this.get(0).appendChild(children);
            }else if(children instanceof HTMLCollection){
                for(let i = 0; i <children.length; i++){
                    this.get(0).appendChild(children[i]);
                }
            }else if(children.jquery === true){
                children.each(node => this.get(0).appendChild(node));
            }
        },
        find (selector) {
            let array = [];
            for(let i = 0 ; i < elements.length; i++){
                const elements2 = Array.from(elements[i].querySelectorAll(selector));
                array = array.concat(elements2);
            }
            array.oldApi = this; //指向旧 api
            return jQuery(array);
        },
        each (fn) {
            for(let i = 0; i < elements.length; i++){
                fn.call(null, elements[i],i);
            }
            return this;
        },
        parent () {
            const array = [];
            this.each((node) => {
                if(array.indexOf(node.parentNode) === -1){
                    array.push(node.parentNode);
                }
            });
            return jQuery(array);
        },
        children () {
            const array = [];
            this.each((node) => {
                array.push(...node.children);
            });
            return jQuery(array);
        },
        print () {
            console.log(elements);
        },
        //闭包:函数访问外部变量
        addClass (className) {
            for(let i = 0; i < elements.length; i++){
                const element = elements[i];
                element.classList.add(className);
            }
            return this;
        },
        oldApi: selectorOrArrayOrTemplate.oldApi,
        end () {
            return this.oldApi;// this就是新的api
        }
    }
}

//代码优化
window.$ = window.jQuery = (selectorOrArrayOrTemplate) => {
    let elements;
    if(typeof selectorOrArrayOrTemplate === "string"){
       if(selectorOrArrayOrTemplate[0] === "<"){
            elements = [createElement(selectorOrArrayOrTemplate)];
       }else{
            elements = document.querySelectorAll(selectorOrArrayOrTemplate);
       }
    }else if(selectorOrArrayOrTemplate instanceof Array){
        elements = selectorOrArrayOrTemplate;
    }

    function createElement (String){
        const container = document.createElement("template");
        container.innerHTML = string.trim();
        return container.content.firstChild;
    }

    const api = Object.create(jQuery.prototype);
    Object.assign({
        elements: elements,
        oldApi: selectorOrArrayOrTemplate.oldApi,
    });
    return api;
}

jQuery.fn = jQuery.prototype  = {
    constructor:jQuery,
    jQuery: true,
    get (index) {
        return this[index];
    },
    appendTo (node) {
        if( node instanceof Element){
            // 遍历 elements,对每个 el 进行 node.appendChild 操作
            this.each(el => node.appendChild(el));
        }else if(node.jquery === true){
            // 遍历 elements,对每个 el 进行 node.get(0).appendChild(el))  操作
            this.each(el => node.get(0).appendChild(el))
        }
    },
    append (children) {
        if(children instanceof Element){
            this.get(0).appendChild(children);
        }else if(children instanceof HTMLCollection){
            for(let i = 0; i <children.length; i++){
                this.get(0).appendChild(children[i]);
            }
        }else if(children.jquery === true){
            children.each(node => this.get(0).appendChild(node));
        }
    },
    find (selector) {
        let array = [];
        for(let i = 0 ; i < this.length; i++){
            const elements2 = Array.from(this[i].querySelectorAll(selector));
            array = array.concat(elements2);
        }
        array.oldApi = this; //指向旧 api
        return jQuery(array);
    },
    each (fn) {
        for(let i = 0; i < this.length; i++){
            fn.call(null, this[i],i);
        }
        return this;
    },
    parent () {
        const array = [];
        this.each((node) => {
            if(array.indexOf(node.parentNode) === -1){
                array.push(node.parentNode);
            }
        });
        return jQuery(array);
    },
    children () {
        const array = [];
        this.each((node) => {
            array.push(...node.children);
        });
        return jQuery(array);
    },
    print () {
        console.log(this);
    },
    //闭包:函数访问外部变量
    addClass (className) {
        for(let i = 0; i < this.length; i++){
            const element = this[i];
            element.classList.add(className);
        }
        return this;
    },
    end () {
        return this.oldApi;// this就是新的api
    }
}
const $div = $('<div><span>1</span></div>');
const $childList = $('.child');
$('body').append(childList);

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

xiaobangsky

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

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

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

打赏作者

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

抵扣说明:

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

余额充值