美文网首页Web前端之路我爱编程
从Console中看看jQuery的原型链

从Console中看看jQuery的原型链

作者: Annnnnn | 来源:发表于2017-08-07 13:03 被阅读177次

写在最前

这不是一篇分析源码的文章——因为作者也没有怎么看源码。本文主要分析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 //true
jQuery.fn.init.prototype === jQuery.prototype //true

在完成这三个的指向之后就可以满足我们起初的需求:

  • 调用jQuery()可以返回一个实例
  • jQuery自己也是构造函数可以被显式new来构建实例
  • 实例的方法绑定在了原型链上

当然了jQuery里面还有方法是绑定在jQuery本身的,绑定在原型链上的方法通过jQuery('#xxx').xxx调用,这个是相对某个元素的方法,绑定在jQuery本身的方法通过$.xxx调用,这个是某种特定的静态方法。我们现在只是讨论基础的jQuery在最外层构建时这些prototype属性都是怎么关联的。想深入了解的欢迎去读源码——

正向梳理一遍

再回过头来看上文提到的三个需求:

  • 调用jQuery()可以返回一个实例
  • jQuery自己是构造函数可以被显式new来构建实例
  • 实例的方法绑定在了原型链上

如果让你来写一个你怎么写?ok,我们一步一步来

调用jQuery()可以返回一个实例

//v1.0
var j = function(selector){
  return new init(selector); 
}
var init = function() {...}

返回的这个实例可以调用原型链方法

//v2.0
//即fn.init的原型应该是j.prototype
var 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.prototype
var a = new j(1) //1
a.setColor('red') // red

init方法也要从原型链上调用

//v3.0
var 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.fn
var 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.fn
var a = new j(1)
a.setColor('red')

至此我们便写好了一个jQuery初级版原型链的一个构建。里面很多操作更多的是为了让暴露的变量尽可能的少,所以在原型链构件上有一种循环赋值的赶脚哈哈哈。有兴趣的同学可以继续研究。

最后

惯例po作者的博客,不定时更新中——
有问题欢迎在issues下交流,捂脸求star=。=

相关文章

  • 从Console中看看jQuery的原型链

    写在最前 这不是一篇分析源码的文章——因为作者也没有怎么看源码。本文主要分析jQuery中到底是如何进行构造原型链...

  • 前端JS进阶五(原型)

    Zepto中如何使用原型 Zepto使用原型源码分析 jQuery中如何使用原型 jQuery使用原型源码分析 原...

  • zepto与jquery原型链解析

    1. zepto原型链 2. jquery原型链 3. 为何要把原型方法放在 $.fn 只有 $ 会暴露在 win...

  • jQuery核心技术

    立即执行函数 模块化开发 jQuery对象继承原型链上的方法 jQuery.fn.entend和jQuery.ex...

  • 原型、原型链

    (什么是原型、原型链?有什么作用) JavaScirpt深入之从原型到原型链 图解 Javascript 原型链 ...

  • 原型与新版的类-class

    首先来理解原型原型 === 共用属性可以先看看方姐的几篇文章:什么是JS原型链JS 中 proto 和 proto...

  • 深入理解原型对象和原型链

    原型对象和原型链在前端的工作中虽然不怎么显式的使用到,但是也会隐式的使用了,比如使用的jquery,vue等啦。在...

  • 2018-10-29 关于js原型链的讨论

    起源:为什么使用原型链 使用原型链是为了实现继承,那js的继承为什么选择了原型链呢?我们来看看网络的解释 http...

  • JavaScript小进阶9--一张图看尽原型及底层模拟

    一张图就可以看尽js的原型:注意红色箭头,就是js的原型链!! 由上面,两个注意: 1. console.log(...

  • 06-老马jQuery教程-jQuery高级

    1.jQuery原型对象解密 jQuery里面的大部分API都是在jQuery的原型对象上定义的。jQuery源码...

网友评论

    本文标题:从Console中看看jQuery的原型链

    本文链接:https://www.haomeiwen.com/subject/xqaolxtx.html