用 JS 封装一个库的基本思路

92 阅读1分钟

尝试用JS来实现jQuery中简单的API: addClass

注:为方便理解,变量名用了中文名

一、使用闭包实现

function jQuery(选择器) {
    const 标签伪数组 = document.querySelectorAll(选择器)
    const 标签数组 = Array.from(标签伪数组)
    return {
        addClass(className) {
            标签数组.forEach((标签) => {
                标签.classList.add(className)
            })
            return this
        },
        removeClass(className) {
            标签数组.forEach((标签) => {
                标签.classList.remove(className)
            })
            return this
        }
    }
}
const $ = jQuery

// 这样就能用jQuery的方式调用了,return this是为了可以链式调用
$('li').addClass('red').removeClass('green')
  • querySelectorAll获取到的是一个伪数组,伪数组和真数组的区别在于,伪数组只有数组的自由属性,但没有数组的共有属性
  • 用闭包实现的缺点:
    • 当多次调用$ 时, 如调多次下面的代码,会在内存中重复创建addClass,造成内存冗余
    • $('li').addClass('red')

二、使用构造函数实现

function jQuery(选择器) {
    // 为了不使用new调用
    if (!(this instanceof jQuery)) {
        return new jQuery(选择器)
    }
    const 标签伪数组 = document.querySelectorAll(选择器)
    this.标签数组 = Array.from(标签伪数组)
}
jQuery.prototype = {
    constructor: jQuery,
    addClass(className) {
        this.标签数组.forEach((标签) => {
            标签.classList.add(className)
        })
        return this
    },
    removeClass(className) {
        this.标签数组.forEach((标签) => {
            标签.classList.remove(className)
        })
        return this
    }
}
const $ = jQuery
$('li').addClass('red').removeClass('green')

三、使用class实现

class jQueryClass {
    constructor(选择器) {
        const 标签伪数组 = document.querySelectorAll(选择器)
        this.标签数组 = Array.from(标签伪数组)
    }
    addClass(className) {
        this.标签数组.forEach((标签) => {
            标签.classList.add(className)
        })
        return this
    }
    removeClass(className) {
        this.标签数组.forEach((标签) => {
            标签.classList.remove(className)
        })
        return this
    }
}
function jQuery(选择器) {
    return new jQueryClass(选择器)
}
const $ = jQuery
$('li').addClass('red').removeClass('green')