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

总体架构

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

从jQuery的表达式能够看出两点:css

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

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

 

分析一:无new构建

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

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的原型,共享了本应该私有的属性。ide

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构建方法的关键所在:原型传递。源码分析

直接上代码:this

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对象。spa

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

 

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

 

分析二:链式调用

当使用了new关键字后,jQuery的全部方法中的this都指向了新建的实例,因此咱们只要在方法最后返回this,就能够实现链式调用。然而:

摘自Aaron的JQ源码分析

最糟糕的是全部对象的方法返回的都是对象自己,也就是说没有返回值,这不必定在任何环境下都适合。


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

相关文章
相关标签/搜索