从Console中看看jQuery的原型链
来源:互联网 发布:淘宝领卷公众号 编辑:程序博客网 时间:2024/05/16 23:49
写在最前
这不是一篇分析源码的文章——因为作者也没有怎么看源码。本文主要分析jQuery中到底是如何进行构造原型链的。思路是通过逆推来抛出问题再用正推的方式来分析解决问题。欢迎关注作者博客,不定期更新中——
jQuery是什么
首先你知道jQuery有两种使用方法吧?
一种是jQuery('#xxx');一种是new jQuery('#xxx');
这两种方式都会返回一个实例。其原型链应该有一大堆方法。比如:jQuery('#xxx').css;jQuery('#xxx').attr;jQuery('#xxx').html...等等。
并且我们应该认识到jQuery这个函数一方面返回了一个实例,另一方面其本身也是构造函数(因为 new jQuery),那么其原型链也应该指向了那一大堆方法。我们一步步打印一下来验证下猜测:
console.log(jQuery) // 来看下jQuery函数体function ( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' // Need init if jQuery is called (just allow error to be thrown if not included) return new jQuery.fn.init( selector, context ); } //小技巧,可以引入没有压缩过的jQuery进行学习,这样备注,变量名会抱持原样。
好的果然没猜错,我们看到了一个构造函数为jQuery.fn.init
。通过new这个构造函数就可以采用第一种jQuery()的形式来生成实例。接下来验证下jQuery.fn.init
的prototype属性上是不是有我们猜测的一大堆方法。
console.log(Object.keys(jQuery.fn.init.prototype))// ["jquery","constructor","init","show","hide","toggle","on","one", "off","detach","remove","text","append", ...]
从结果中也可以知道我们的推测是正确的。在jQuery.fn.init
的prototype中有着封装的方法可供实例调用。
new jQuery('#xxx')
验证了无new构造实例的形式之后再来看下对于jQuery同时应该是个构造函数的猜测。
console.log(Object.keys(jQuery.prototype))//["jquery","constructor","init","show","hide","toggle","on","one", "off","detach","remove","text","append", ...]console.log(jQuery.prototype === jQuery.fn.init.prototype) //true
可以看出jQuery也确实是一个构造函数其prototype和jQuery.fn.init的一样都指向了那一大堆方法。
init方法
让我们再看下这段代码:
function ( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' // Need init if jQuery is called (just allow error to be thrown if not included) return new jQuery.fn.init( selector, context ); }
这里面返回的构造函数jQuery.fn.init
我们可以看成是调用了jQuery.fn的init方法。同时细心的同学们应该可以观察到,在jQuery.fn.init.prototype
中也有个方法叫init!。那么是不是。。让我们打印一下我们的猜测:
console.log(jQuery.fn.init.prototype.init === jQuery.fn.init) //true
发现了么同学们!既然jQuery.fn可以调用jQuery.fn.init其原型链上的方法,那么一定有:
jQuery.fn.init.prototype === jQuery.fn // true
小结
好的现在大家可能有种似懂非懂的感觉?来看下面这张图来总结下我们的发现。
通过前文加上我们上图的展示,原型链的关系已经很明了了。在原型链上绑定了很多很多方法确定无疑。与此同时有三个东西指向了该原型链即:
jQuery.fn === jQuery.fn.init.prototype //truejQuery.fn.init.prototype === jQuery.prototype //true
在完成这三个的指向之后就可以满足我们起初的需求:
- 调用jQuery()可以返回一个实例
- jQuery自己也是构造函数可以被显式new来构建实例
- 实例的方法绑定在了原型链上
当然了jQuery里面还有方法是绑定在jQuery本身的,绑定在原型链上的方法通过jQuery('#xxx').xxx
调用,这个是相对某个元素的方法,绑定在jQuery本身的方法通过$.xxx
调用,这个是某种特定的静态方法。我们现在只是讨论基础的jQuery在最外层构建时这些prototype属性都是怎么关联的。想深入了解的欢迎去读源码——
正向梳理一遍
再回过头来看上文提到的三个需求:
- 调用jQuery()可以返回一个实例
- jQuery自己是构造函数可以被显式new来构建实例
- 实例的方法绑定在了原型链上
如果让你来写一个你怎么写?ok,我们一步一步来
调用jQuery()可以返回一个实例
//v1.0var j = function(selector){ return new init(selector); }var init = function() {...}
返回的这个实例可以调用原型链方法
//v2.0//即fn.init的原型应该是j.prototypevar fn = {}var xxx = function() {}fn.init = function(selector) {console.log(selector)}var j = function(selector){ return new fn.init(selector); }xxx.prototype = { setColor: function(color){console.log(color)} ...}fn.init.prototype = xxx.prototypevar a = new j(1) //1a.setColor('red') // red
init方法也要从原型链上调用
//v3.0var xxx = function() {}var j = function(selector){ return new j.fn.init(selector); //借用j.fn来找到原型链方法,不然找不到}j.fn = xxx.prototype = { //j本身是构造函数 init: function(selector) { console.log(selector) }, setColor: function(color) { console.log('setColor:' + color) }}j.fn.init.prototype = j.fnvar a = new j(1)a.setColor('red')
jQuery自己是构造函数可以被显式new来构建实例
//v3.0//将xxx替换为j,那么j当做构造函数后其原型链也指向了那一堆方法var j = function(selector){ return new j.fn.init(selector); //借用j.fn来找到原型链方法,不然找不到}j.fn = j.prototype = { //j本身是构造函数 init: function(selector) { console.log(selector) }, setColor: function(color) { console.log('setColor:' + color) }}j.fn.init.prototype = j.fnvar a = new j(1)a.setColor('red')
至此我们便写好了一个jQuery初级版原型链的一个构建。里面很多操作更多的是为了让暴露的变量尽可能的少,所以在原型链构件上有一种循环赋值的赶脚哈哈哈。有兴趣的同学可以继续研究。
最后
惯例po作者的博客,不定时更新中——
有问题欢迎在issues下交流,捂脸求star=。=
- 从Console中看看jQuery的原型链
- 从OOP的角度重看C++(四)——从程序中看OOP
- 从冒险中看到的
- 从重置input file标签中看jQuery的 .val() 和 .attr(“value”) 区别
- 【从源码看Android】02MessageQueue的epoll原型
- 【从源码看Android】02MessageQueue的epoll原型
- 从“原型”看—计算机科学的解决问题驱动性
- 从原型链看DOM--Node类型
- 从陆游的词中看人生
- 从silverlight中看到的不同
- 从ACE_LOG中看宏的使用技巧
- 从网站的价值中看网站建设
- 从SVProgressHUD中看NSTimer的内存释放
- 从FreeBSD源码中看到的东西
- 从jQuery看JavaScript
- 通过 console.log($("#MyForm"));,形象的看一下,jQuery对象,都是什么?
- 图片,呵呵,大家可以去我的相册中看看
- 从日常生活中看对象
- 基于 canvas 实现的一个截图小 demo
- Innodb存储引擎的特性
- 基于react的影院购票应用
- Javascript之bind
- 基于 node 的微小爬虫——扒了一下知乎
- 从Console中看看jQuery的原型链
- 基于node的微小服务——细说缓存与304
- 从零实现一个自定义html5播放器
- 基于jQuery的一个“射日”小游戏
- 基于canvas实现波浪式绘制图片
- Android杂记-混淆
- 从HTML5与PromiseA+规范来看事件循环
- 从[] == ![] 看隐式强制转换机制
- 给文档添加一组掘金的「小盾牌」