javascript 跟Aaron大神学习jquery源码笔记

/*

通过new操作符构建一个对象,一般经过四步:

A.创建一个新对象

B.将构造函数的作用域赋给新对象(所以this就指向了这个新对象)

C.执行构造函数中的代码

D.返回这个新对象

最后一点就说明了,我们只要返回一个新对象即可。

其实new操作符主要是把原型链跟实例的this关联起来,这才是最关键的一点,

所以我们如果需要原型链就必须要new操作符来进行处理。否则this则变成window对象了。

*/

/*

var $$ = ajQuery = function(selector) {

  this.selector = selector;

  return this

}

ajQuery.fn = ajQuery.prototype = {

  selectorName:function(){

    return this.selector;

  },

  constructor: ajQuery

}

var a = new $$(‘aaa‘); //实例化

a.selectorName() //aaa //得到选择器名字

首先改造jQuery无new的格式,我们可以通过instanceof判断this是否为当前实例:

var $$ = ajQuery = function(selector) {

  if(!(this instanceof ajQuery)){ 只要这个 构造函数 出现在实例的原型链上 那么 instanceof 就会返回true

    return new ajQuery(selector);

  }

  this.selector = selector;

  return this

}

但是注意千万不要像下面这样写:

var $$ = ajQuery = function(selector) {

  this.selector = selector;

  return new ajQuery(selector);

}

Uncaught RangeError: Maximum call stack size exceeded

这样会无限递归自己,从而造成死循环并且溢出。

jQuery为了避免出现这种死循环的问题,采取的手段是把原型上的一个init方法作为构造器

var $$ = ajQuery = function(selector) {

//把原型上的init作为构造器

  return new ajQuery.fn.init( selector );

}

ajQuery.fn = ajQuery.prototype = {

  name: ‘aaron‘,

  init: function() {

    console.log(this)

  },

  constructor: ajQuery

}

这样确实解决了循环递归的问题,但是又问题来了,

init是ajQuery原型上作为构造器的一个方法,那么其this就不是ajQuery了,

所以this就完全引用不到ajQuery的原型了,

所以这里通过new把init方法与ajQuery给分离成2个独立的构造器。

静态与实例方法共享设计

保留上一节分割出2个构造器的疑问,我们先看看jQuery在接口的设计:

遍历方法:

$(".aaron").each() //作为实例方法存在

$.each() //作为静态方法存在

这是最常见的遍历方法,第一条语句是给有指定的上下文调用的,

就是(".aaron")获取的DOM合集,第二条语句$.each()函数可用于迭代任何集合,

无论是“名/值”对象(JavaScript对象)或数组。

在迭代数组的情况下,回调函数每次都会传递一个数组索引和相应的数组值作为参数。

本质上来说2个都是遍历,那么我们是不是要写2个方法呢?

我们来看看jQuery的源码:

jQuery.prototype = {

  each: function( callback, args ) {

    return jQuery.each( this, callback, args );

  }

}

实例方法取于静态方法,换句话来说这是静态与实例方法共享设计,

静态方法挂在jQuery构造器上,原型方法挂在哪里呢?

我们上节不是讲了内部会划分一个新的构造器init吗?

jQuery通过new原型prototype上的init方法当作构造器,

那么init的原型链方法就是实例的方法了,

所以jQuery通过2个构造器划分2种不同的调用方式一种是静态,一种是原型。

方法是共享的,并且实例方法取于静态方法,2个构造器是完全隔离的 ,这个要如何处理?

看看jQuery给的方案:

画龙点睛的一处init.prototype = jQuery.fn,把jQuery.prototype原型的引用赋给jQuery.fn.init.prototype的原型,

这样就把2个构造器的原型给关联起来了。

ajQuery.fn = ajQuery.prototype = {

  name: ‘aaron‘,

  init: function(selector) {

    this.selector = selector;

  return this;

  },

  constructor: ajQuery

}

ajQuery.fn.init.prototype = ajQuery.fn

这段代码就是整个结构设计的最核心的东西了,有这样的一个处理,整个结构就活了!

不得不佩服作者的设计思路,别具匠心。

通过原型传递解决问题,把jQuery的原型传递给jQuery.prototype.init.prototype。

换句话说jQuery的原型对象覆盖了init构造器的原型对象,因为是引用传递所以不需要担心这个循环引用的性能问题。

*/

时间: 2024-10-13 19:58:41

javascript 跟Aaron大神学习jquery源码笔记的相关文章

前端学习-jQuery源码学习

jQuery 2 的版本与jQuery 1的版本相比,没有再考虑IE6,7,8的兼容问题,因此使用时如果不用考虑IE6,7,8就用jQuery 2的版本,如果需要考虑IE6,7,8就使用jQuery 1的版本. jQuery对象是一个以DOM为对象的特殊数组,并包含大量方法,简单可以理解为: function jQuery(){     var jquery = [dom1, dom2, dom3];     jquery.fn1 = function(){-};     jquery.fn2

jquery 源码笔记:

1.使用了jquery,但是觉得了解 jquery的源码才能 更容易知道怎么使用,所以在网上找了一些 jquery的源码 笔记 还有看了 妙味课堂 的 一部分视频,现在写一些总结. 一.  jquery的 总体架构: 1.jquery 有良好的对外接口,  window.jQuery = window.$ = jQuery; 现在 是 通过jquery 2.0.3 源码的分析: (21,94)  21—94行, 定义了一些变量和函数,   jQuery = function(); (96,283

大神如何阅读源码

1.腾讯IMWEB负责人说: 首先,搞清楚自己要读懂他们的原因和动机. 其次,可以先看下这些优秀框架或者库的设计文档和架构图,这样会让你宏观上对一些概念有些认识. 然后,从你最感兴趣的一个点,开始设置断点,跟进去看发生了哪些事情. 和架构设计哪一块是match的. 有人补充:最快,最易懂方法.断点单步调试. 如:jquery中 $.fn.show 源码是如何实现的. 自己写个 $('#test').show(),打上断点.单步调试.那么你可以看到jquery中每一步发生了什么事情.分析即可. 2

jquery源码笔记(三): jquery.prototype的一些方法 和属性 init

jquery.fn = jquery.prototype = { 添加实例属性和方法, jquery: 版本, constructor: 修正指向问题 init(): 初始化 和 参数管理 selector:存储选择字符串 length: this 对象的长度 toArray(): 转数组 get(): 转原生集合 pushStack(): jquery 对象入栈 each()  :  便利集合 ready():DOM加载的接口 slice(): 集合的截取 first(): 集合的第一项 la

jquery源码笔记(四): jquery.extend=jquery.fn.extend

extend()  方法,   合并两个或更多对象的属性到第一个对象中,jQuery后续的大部分功能都通过该函数扩展, 当参数只有一个对象时,则将对象的属性添加到jQuery对象中. jquery 中扩展插件的形式:  2种方法 $.extend({ //扩展工具方法 aaa:function(){ alert(10); }, bbb:function(){ alert(20) } }); $.fn.extend({ //扩展jquery实例方法 aaa:function(){ alert("f

jQuery源码笔记——三

将类数组对象转化为数组对象 javascript中有许多类数组对象,比如HTMLCollection,NodeList,arguments.她们的特点是和数组一样有length属性,并且有0,1,2这样的位置属性.在代码编写中我们经常需要将他们转化为数组对象. //mini类数组对象 var arrayLike = { 0: "a", 1: "b", 2: "c", length: 3 } console.log(Array.prototype.

jQuery源码笔记——二

jQuery选择这样返回对象 var jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context );//从jQuery.fn里调用的方法 }; jQuery.fn = jQuery.prototype = { //这里jQuery.prototype,目前可以删除. init: function(){ console.log("初始化完成"); return this; }

jQuery源码笔记——数据缓存

数据数据是为了解决内存泄露,他的原理是,当我们将数据存储到一个对象上面,实际上是将所有的数据存到一个单独的数据对象里,而这个对象只提供一个接口,这个接口可以访问自己存在数据对象里自己的数据. 这是一个简单的数据数据 var data = {}; function set(obj,name,value){ //在对象上存储一个属性,用作访问数据的接口 obj.expando = 1; //初始化对象,并在我们接口所提供的位置存放数据 data[obj.expando] = {} data[obj.

jquery源码笔记(二): 定义的变量,

jquery中定义的变量,1.防止污染全局变量,2.自定义变量有助于压缩优化,3.有助于后期维护 rootjquery ,  jquery的根目录jquery(document), core_strundefined= typeof undefined,      core_strundefined 存的就是string类型的 undefined 判断a是不是不存在: 一般判断方法,有2种: window.a ==undefined; //只使用这个 可能在IE中不行, typeof windo