jQuery源码阅读笔记(5)

完善核心函数

之前所写的核心函数,并不完善,因为部分核心方法也没有写

添加了部分原型方法后,现在可以完善一下,有一部分也是我没注意的,在此一块加上

函数的漏缺

哪一个函数的漏缺?作为参数放入核心函数中的函数

有两个点

  • 函数的参数

  • 函数的this

我们填写的函数,执行时会可以收到一个参数,提供的是$对象

为的就是防止$命名的冲突,为了这一点,官方也是提供了两种方式获取核心函数,jQuery$,甚至还有一个解决命名冲突的函数noConflict(),也就是释放$的使用权

感觉还是不过瘾,还在函数内传给你使用权,保证获得的会是jQuery对象,且可以自定义参数名

jQuery(function ($) {
    console.log($); // jQuery
    console.log(this);// document
});

对于这一点之前没有研究好,在翻阅一些老代码时发现了这种写法,为的就是防冲突,又不用写那么长的jQuery

而另一点则是函数的this指向,此处是指向原生的document对象,原因也很容易理解

虽然几乎不会用,一个箭头函数就把它无视掉了

修补工程

//...
else if (isFunction(selector)) {
    //[].push.call(this, document);
    this.push(document);//原型方法已添加,所以可以简化一些
    if (document.readyState === 'complete') {
        selector.call(document, jQuery);//修改指向,加入参数
    } else {
        document.addEventListener('DOMContentLoaded', selector.bind(document, jQuery));//使用bind()修改绑定
    }
}
//...
第二参数

第二参数主要限制第一参数的检索范围,之前没有说是因为还有一点,回退指针

主要补上这几点

  • 回退指针指向
  • 第二参数使用

只有一个参数时,在参数是字符串,且不是HTML结构字符串的情况下,就直接当成选择器,而不管有没有选择到的元素,这个对象的回退指针都要指向document

而第二参数,只是先按第一参数执行好,然后再从它的范围中,按第一参数的字符串来搜索元素,且对象的回退指针会指向第二参数,就不是document

有点绕,整理一下就是,第二参数也是一个$对象,不过它只会存在于,这个即将返回的对象的指针当中,可以使用end()回退

//...
//对于字符串
else if (isString(selector)) {
    //新加入一条,对于纯数字,直接退出
    if (isNumeric(selector)) {
        return this;
    }
    //是否是一个HTML结构,是则无需指针,且不搭理第二参数
    if (isHTML(selector)) {
        const div = document.createElement('div');
        div.innerHTML = selector;
        this.push(...div.children);//调优
        //[].push.apply(this, div.children);
    } else {
        //查看是否有第二个参数
        if (context) {
            //如果就是一个jQuery对象
            if (context.jquery) {
                this.prevObject = context.each((_i, value) => {
                    this.push(...value.querySelectorAll(selector));
                });
            } else {
                /*
                巧用返回值和this,使用this构造函数减少层间查找
                利用箭头函数使内部this依然指向外部即将返回的新对象
                */
                this.prevObject = this.constructor(context).each((_i, value) => {
                    this.push(...value.querySelectorAll(selector));
                });
            }
        } else {
            //[].push.apply(this, document.querySelectorAll(selector));
            this.push(...document.querySelectorAll(selector));
            //加上回退
            this.prevObject = $(document);
        }
    }
}

其实在后续使用中发现有一个问题,关于第二参数的

实现选择器功能,依靠的是querySelector()querySelectorAll(),但它们并不能用于伪类选择器

$中的选择器花样多,啥都行,不仅加入伪类选择器,而且还有很多自定义类型

在这里想指出的是一个判断问题

<!--三层嵌套div-->
<body>
    <div>
        <div>
            <div>
            </div>
        </div>
    </div>
</body>

对于这段结构,选择器的表现

//最外层的div选择到,然后在它的内部选择div,最后选择到内层的两个div
$('div', 'body>div');

这样是没问题,也没有意见,如果换成这样,差异出来了

$('div>div', 'body>div');

是怎样的差异呢?

对于div>div选择器,在官方的表现是,只选择到最内层的那一个

而使用querySelector(),它的想法并不一样,依然是两个,它也有自己的道理

对于第二层的div来说,它的父元素为div,那它本身自然也符合div>div的条件

而官方的表现,事实上是把选择器拼接起来,然后进行选择,是符合CSS选择器条件的

/*符合这段选择器的,只有最内层的div*/
body>div>div>div{}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值