自己写个 JQuery


JQuery 是最流行的 js 前端框架之一,它封装了js操作,提供了众多好用的特性,让程序员开发起来流程无比。

以下是一些简单的特性:

$('#name') // 相当于 document.getElementById('name')
$('.age') // document.getElementsByClassName('age')
$('p')    // document.getElementsByTagName('p')

$('#name').addClass('top') // 添加类
$('#name').css('display: none') // 添加样式
$('p').html()

// 更多...

这么多好用的特性到底是如何实现的,非常简单,本文用几行代码解开神秘面纱!

实现选择器

// mjquery.js

// 自定义 $ 为函数
$ = function (s) {
    if (startWith(s, '#')) {
        // 返回通过 id 查找到的元素
        return document.getElementById(s.substring(1));
    } else if (startWith(s, '.')) {
        // 通过 class 查找到的元素
        return document.getElementsByClassName(s.substring(1));
    } else {
        // 通过 tagname 查找到的元素
        return document.getElementsByTagName(s);
    }
};

// 判断第一个字符的类型
startWith = function (s, flag) {
    return s.substring(0, 1) == flag;
};

// 实例应用
$('#name').style.color = 'red';
$('.age')[0].style.color = 'blue';
$('p')[0].style.color = 'cyan';

测试:

<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
    <span id="name">chiyiw</span>
    <span class="age">21</span>
    <p>hello world</p>
    <script src="mjquery.js"></script>
</body>
</html>

结果:

上面的$其实就是一个普通的方法名,你可以用这个方法定义更多自己的方法名,比如$F,$$等。JQuery就是这样干的。

实现通用的函数

上面介绍的其实和我们平时自己定义的函数没有什么区别,只是方法名特殊点而已,但是JQuery中诸如css(),html()等方法,不仅能给通过$获取到的元素使用,而且能被任意元素使用,这是如何做到的?

为了使“山寨JQuery”能够使用$('#name').css()等方法,并对所有的元素都能使用,我们需要重写 HTMLElement.prototype,为其添加方法。

在Dom标准中,所有的 HTML 元素都继承自 HTMLElement,而 HTMLElement 继承自 Element,Element 继承自 Node。所以我们只要 拓展 HTMLElement.prototype,就能为所有的元素添加方法了!这个prototype,是 Element成员的集合,包含变量和方法,你可以类比为 java中的 this(当然,不等价)。

// mjquery.js

// 添加 css 方法
HTMLElement.prototype.css = function(str){
    // 获取到原来的 style 值
    var old = this.getAttribute('style');
    // 添加新的 style 属性
    this.style = old+';'+str;
    // 为了支持链式调用,返回本身
    return this;
}
// 添加 addClass 方法
HTMLElement.prototype.addClass = function (str) {
    this.className += ' '+str;
    return this;
}

// 添加 html 方法
HTMLElement.prototype.html = function (str) {
    
    if (typeof str == 'string') { // 传入的值为字符串,表示赋值
        this.innerHTML = str;
        return this;
    } else {                      // 传入的值为空,表示取值
        return this.innerHTML;
    }
};

// 应用测试
$('#name').css('font-size:30px');
$('#name').addClass('classA');
$('#name').addClass('classB');
$('p')[0].html('this is chiyiw');

结果:

可以看到 样式、class均被成功添加,定义的函数生效。

到这里我们自己的 JQuery 就已经有好几个方法了,要实现更多的特性,只需要使用类似的方法去实现。

当然,jquery到底如何实现的与此无关~~