• jQuery源码学习(1):整体架构


    整体架构

    $().find().css().hide()

    从jQuery的表达式可以看出两点:

    1. jQuery的构建方式
    2. jQuery的调用方式

    下面从这两方面来窥探jQuery的整体架构:

     

    分析一:无new构建

    这一点是推测jQ构建方式的重点。既然没有使用new,jQ必定在函数中返回了一个实例,也就是通过工厂模式来创建对象。

    var aQuery = function(select){
      var o = new Object();
      o.select = select;
      o.myFunc = function(){};
    }

    然而这种方法显然非常笨拙,每次新建一个对象实例都必须声明其所有共用方法。能不能把构造函数与原型模式融入到这里面来呢?

    var aQuery = function(selector){
      return aQuery.prototype.init(selector);
    };
    
    aQuery.prototype = {                                  // aQuery的原型
      init: function(selector){                  // init作为新的构造函数
        this.selector = selector;
    return this; }, myFunc: function(){} }; console.log(aQuery('s1'));

    代码运行之后,在控制台显示的是下面这样的结果:

    { 
      init: [Function],
      myFunc: [Function],
      selector: 's1'
    }

    this指向了aQuery的原型对象,并且共用了所有方法。然而这里面的陷阱在于,由于我们并没有new一个新对象,所以构造函数内部的this指向了aQuery的原型,共享了本应该私有的属性。

    var a1 = aQuery('s1');
    var a2 = aQuery('s2');
    console.log(a1.selector);      // s2

    那么是不是只要返回一个新实例就可以了呢?

    var aQuery = function(selector, context){
      return (new aQuery.prototype.init(selector, context));
    };
    
    aQuery.prototype = {...};
    
    var a1 = aQuery('s1');
    var a2 = aQuery('s2');
    console.log(a1.selector);      // s1
    console.log(a1);         //{ selector: 's1' }   myFunc不见了!

    由上可见,new关键字新建了一个空对象,使构造函数内部的this指向该对象,解决了属性公有的问题(这部分知识点请参考Javascript对象部分)。然而同时,也丢失了aQuery.prototype。那么jQuery是怎么解决这个问题的呢?这就是jQuery构建方法的关键所在:原型传递。

    直接上代码:

    var aQuery = function(selector){
      return (new aQuery.prototype.init(selector));
    };
    
    aQuery.prototype = {                                  // aQuery的原型
      init: function(selector){                  // init作为新的构造函数
        this.selector = selector;
        return this;
      },
      myFunc: function(){
        return "aQuery.func";
      }
    };
    aQuery.prototype.init.prototype = aQuery.prototype;
    
    var a1 = aQuery('s1');
    var a2 = aQuery('s2');
    console.log(a1.selector);      // s1
    console.log(a1.myFunc());      // aQuery.func

    其实本质上讲,init构建出来的这个对象,就是jQuery对象。

    这样,我们总算理清了jQuery无new构建的原理。使用工厂模式返回一个实例,并将该实例构造函数的原型指向aQuery原型本身,实现了私有属性和共有方法。

    各中关系如图所示,其中fn指代了jQuery的原型对象。

     

    分析二:链式调用

    当使用了new关键字后,jQuery的所有方法中的this都指向了新建的实例,所以我们只要在方法最后返回this,就可以实现链式调用。然而:

    摘自Aaron的JQ源码分析

    最糟糕的是所有对象的方法返回的都是对象本身,也就是说没有返回值,这不一定在任何环境下都适合。


    Javascript是无阻塞语言,所以他不是没阻塞,而是不能阻塞,所以他需要通过事件来驱动,异步来完成一些本需要阻塞进程的操作,这样处理只是同步链式,异步链式jquery从1.5开始就引入了Promise,jQuery.Deferred后期在讨论。

  • 相关阅读:
    python学习之路基础篇(第八篇)
    python学习之路基础篇(第七篇)
    python学习之路基础篇(第六篇)
    python学习之路基础篇(第五篇)
    python学习之路基础篇(第四篇)
    目标检测——IoU 计算
    MXNet 中的 hybird_forward 的一个使用技巧
    Anchor 的两种编程实现
    我的目标检测笔记
    动手创建 SSD 目标检测框架
  • 原文地址:https://www.cnblogs.com/timl525/p/5302848.html
Copyright © 2020-2023  润新知