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后期在讨论。

posted @ 2016-03-29 22:31  潘诗瑶  阅读(261)  评论(0编辑  收藏  举报