车大棒浅谈jQuery源码(二)

前言

本来只是一个自己学习jQuery笔记的简单分享,没想到获得这么多人赏识。我自己也是傻呵呵的一脸迷茫,感觉到受宠若惊。

不过还是有人向批判我的文章说,这是基本知识点,完全跟jQuery源码沾不上边。说jQuery博大精深,还要我静下心来研究, 别净整些没用的。弄的我一脸懵逼,WTF?我从头到尾都没有说我讲的多高端,我连标题都写的“浅谈”。就完全不能让我等菜鸟慢慢先从的简单的入手吗?

但是有位名为“萌新”三好童鞋,就做的非常好。“啪”!,反手就是一拖鞋留言砸过来一串代码。指出说undefined在ES5、ES6标准中只是全局作用域下不能被定义,一旦脱离全局作用域下undefined就能够被定义。

undefined情况补充

所以希望能够像能够像萌新同学狠狠打脸找知识点错误,而不是指出我这个太简单一类的。这个我本来就是个人学习过程的浅谈一下,给菜鸟一点活路吗!

原型prototype

我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。
--《高级程序第三版》-6.23 原型模式

这里我引用了高级程序第三版当中的一段话用来简单描述原型prototype,但是这个玩意具体有什么用?
解释何为原型之前, ⾸先看下⾯的代码:

     //创建一个构造函数
    function Person() {
        this.sayHello = function() {
            console.log('Hello,I am one Dog')
        }
    }

    //创建两个对象
    var dog1 = new Person(),
        dog2 = new Person();

    //两个实例对象进行比较
    dog1.sayHello();
    dog2.sayHello();
    console.log("dog1.sayHello === dog2.sayHello的结果是:" + (dog1.sayHello === dog2.sayHello));

控制台输出结果:

这里dog1,dog2都是构造函数Person的实例,但是两个人的sayHello方法并不完全相等。也就是说dog1和dog2分别在自己所属空间开辟了一块内存。

夭寿啦!单身狗为何不报团取暖,不是说好一起相亲相爱吗!不是说好一起共享种子,一起开黑吗?月黑风高秋名山一起开车吗!

所以为了避免原本每天遭受狗粮侵蚀单身汪继续团结一致,这个时候原型prototype就起到很好的稳定dog群内团结的作用。

    //创建一个构造函数
    function Person(){};
    Person.prototype.sayHello = function(){
        console.log("Hello, I am one Dog")
    }
    
    //创建两个对象
    var dog1 = new Person(),
        dog2 = new Person();
    
    //两个实例对象进行比较
    dog1.sayHello();
    dog2.sayHello();
    console.log("dog1.sayHello === dog2.sayHello的结果是:"+ (dog1.sayHello === dog2.sayHello));

控制台输出结果:

说明此时两名单身狗又团结一致,资源共享sayHello方法。而不是每个私自建立一个空间,去存放sayHello方法。

当实例对象需要寻找sayHello方法的时候,就会先去构造函数Person函数当中寻找sayHello方法,然后Person函数方法当中没有找到,就会去Person的原型当中去找sayHello方法。(同理在JavaScript当中,如果创建多个对象,但是却只共享一个方法。减少了内存的使用,能够优化性能不少。)

资源共享的单身汪

而jQuery里面也充斥不少原型prototype,所以看下面jQuery代码,就会知道相应查找顺序了,同样也能更好的理解后面的代码。

jQuery无new构造

之前第一章,我们有讲过jquery通过如下代码来暴露接口:

window.jquery = window.$ = jQuery

举个栗子:

$("#box")   =  jQuery("#box")

那么jQuery这个函数开始执行,此时让我们打开jQuery源码,看看jQuery内部是如何实现的。

(function(window, undefined) {
    var
    // ...
    jQuery = function(selector, context) {
        return new jQuery.fn.init(selector, context, rootjQuery);
    },

    jQuery.fn = jQuery.prototype = {
        init: function(selector, context, rootjQuery) {
            // ...
        }
    }
    jQuery.fn.init.prototype = jQuery.fn;

})(window);

估计有童鞋 jQuery.fn.init.prototype = jQuery.fn 这一句都会被卡主,满脸黑人问号。但是这句真的算是 jQuery 的绝妙之处。理解这几句很重要,分别解析一下:

来自灵魂抽象派画师--车大棒

1、首先要明确,使用 $(‘xxx’) 这种实例化方式,其内部调用的是return new jQuery.fn.init(selector, context, rootjQuery) 这一句话,也就是构造实例是交给了 jQuery.fn.init() 方法取完成。

2、将jQuery.fn.init 的 prototype 属性设置为jQuery.fn,那么使用 new jQuery.fn.init() 生成的对象的原型对象就是jQuery.fn ,所以挂载到 jQuery.fn 上面的函数就相当于挂载到 jQuery.fn.init()生成的 jQuery 对象上,所有使用new jQuery.fn.init()生成的对象也能够访问到 jQuery.fn 上的所有原型方法。

3、也就是实例化方法存在这么一个关系链
jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype ;
new jQuery.fn.init()相当于 new jQuery() ;
jQuery()返回的是 new jQuery.fn.init(),而 var obj = new jQuery(),所以这 2 者是相当的,所以我们可以无 new 实例化 jQuery 对象。

-------来自某博客大牛的小结(看到好多博客上面都有,不清楚谁才是原创)

PS:
原本这里打算把晒上我用思维箭头图画出个整个结构之后,就基本上一句话可以带过了。但是我看到别人博客上这一段总结很好,所以就直接引用了。当然写博客的时候,我就料到直接引用可能会有点影响不好。修改一下,然后用自己语言来说,可能会效果好的多。

但是完全觉得没有必要, 好东西我觉得就应该直接拿出来分享。事实上我本来的学习jQuery源码就是吸收各种视频资源,以及各路大牛博客去学习参考。别人写的好,写的详细这就是无可厚非的。(如果有原话博客主,对我私自引用有意见。留言,我立刻删或者改。)

jQuery的链式调用

早在第一次接触jQuery的时候,就被它风骚的链式调用给吸引了,感觉操作真TMD的6到飞起。
例如:$('div').eq(0).show().end().eq(1).hide();

所以希望待会简单的谈及这个知识点之后,我不希望你们来一句:“大神,这波操作666!!”,而是高呼道:“what?这么简单!”(PS:大牛们请无视这句话,还有不懂这两句话差别的也请无视这句话!)

var oneDog = {
        food : function(){
            console.log("今天晚餐是泡面和一个卤鸡蛋!");
            return this;    
        },
        sad : function(){
            console.log("坐地铁被喂了十几站的狗粮!");
            return this;
        },
        game : function(){
            console.log("今天DOTA2开黑10连跪");
            return this;
        },
    }
    
    oneDog.food().sad().game();       //没错,这样就是实现了链式调用。

然后控制台就能够依次输出每个方法当中的log语句,就是这么简单每次调用返回它自己本身就可以形成一个链式调用。(来!开始喊那句话吧!)

看过前面的小demo之后,让我们回过头来看jQuery的源码是如何实现链式调用。
首先第一步,显示HTML骨架部分:

    <div>我是dog1</div>
    <div>我是dog2</div>

接下来就是jQuery代码

console.log($(''div').eq(0))

这个时候控制台输出结果:

之后在eq(0)后面紧紧跟end()结束的时候,然后相当于整个代码返回给prevObject这个集合了:

//jQuery源码当中的end函数
end: function() {
        return this.prevObject || this.constructor(null);
    }

总的来说,

1、eq(i) 之后留下prevObject 属性,这个属性记录了操作的 jQuery 对象集合;

2、当我们在链式调用 end() 方法后,内部就返回当前 jQuery 对象的 prevObject 属性,完成回溯。

3、和前面我们返回的this的小demo,有异曲同工之妙。

小结:

今天将的知识点比较少,先是带大家回顾了prototype知识点,之后浅谈了一下jQuery的无new的构造结构,以及链式调用的原理。

两篇博客所讲的知识完全没有一些知名大牛博客一篇博客讲的知识点多,但是哪怕能讲懂一个点我也会很欣慰。有句话说的好:
不积跬步,无以至千里;不积小流,无以成江海。

原创文章,文笔有限,才疏学浅,文中若有不正之处,再次再次再次欢迎各位啪啪的打脸赐教。(有句话说的好,重要的词得说三遍。)



我是车大棒,我的目标是星辰与大海!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容

  • 1.jQuery是如何寻找到DOM或者很多方法 $符号选择标签,然后进行事件监听或者DOM操作 可以把$,看成一个...
    大淀桑浮不起來阅读 980评论 1 10
  • jquery是前端常用的库,它的源码也是十分的精妙,我本着敬畏之心来分析它,jquery 代码未压缩总共有1100...
    GarenWang阅读 580评论 0 0
  • 在线阅读 http://interview.poetries.top[http://interview.poetr...
    程序员poetry阅读 114,222评论 24 450
  • 本文转发自github, 原文地址 <a name='js'>JavaScript</a> 介绍js的基本数据类型...
    XDUZ阅读 1,032评论 1 11
  • 有人住高楼,有人处深沟,有人光万丈,有人一身锈,世人万千种,浮云莫去求,斯人若彩虹,遇上方知有。 这样就有了...
    支苑阅读 126评论 0 0