jQuery分离构造器

http://www.imooc.com/code/3401

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

A.创建一个新对象

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

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

  D.返回这个新对象

最后一点就说明了,我们只要返回一个新对象即可。其实new操作符主要是把原型链跟实例的this关联起来,这才是最关键的一点,所以我们如果需要原型链就必须要new操作符来进行处理。否则this则变成window对象了。

下面这个例子,console结果一样。因为都用了new 。如果不用new就不一样了。

var $$ = ajQuery = function(selector) {
        this.selector = selector;
        return this
    }
    var ins = new $$("111");
    console.log(ins);//
    var $$2 = ajQuery2 = function(selector) {
        this.selector = selector;
    }
    var ins2 = new $$2("2222");
    console.log(ins2);//

去掉new 后。ajQuery里的return this就起了作用。

var $$ = ajQuery = function(selector) {
        this.selector = selector;
        return this
    }
    var ins = $$("111");
    console.log(ins);//window
    var $$2 = ajQuery2 = function(selector) {
        this.selector = selector;
    }
    var ins2 = $$2("2222");
    console.log(ins2);//undefined

我们常见的类式写法:

var $$ = ajQuery = function(selector) {
        console.log(this instanceof ajQuery);//true ajQuery被new形式调用时,this就是ajQuery的实例
        this.selector = selector;
        return this
    }
    ajQuery.fn = ajQuery.prototype = {
        selectorName:function(){
            return this.selector;
        },
        constructor: ajQuery
    }
    var ins = new $$("111");
    console.log(ins.selectorName());

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

var $$ = ajQuery = function(selector) {
        console.log(this);//先是window,再是ajQuery的实例
        if(!(this instanceof ajQuery)){
            return new ajQuery(selector);
        }
        this.selector = selector;
        return this
    }
    ajQuery.fn = ajQuery.prototype = {
        selectorName:function(){
            return this.selector;
        },
        constructor: ajQuery
    }
    var ins = $$("111");
    console.log(ins.selectorName());

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

var $$ = ajQuery = function(selector) {
    this.selector = selector;
    return new ajQuery(selector);
}
Uncaught RangeError: Maximum call stack size exceeded

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

静态与实例方法共享设计

jQuery遍历方法:

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

这是最常见的遍历方法,第一条语句是给有指定的上下文调用的,就是(".aaron")获取的DOM合集,第二条语句$.each()函数可用于迭代任何集合,无论是“名/值”对象(JavaScript对象)或数组。在迭代数组的情况下,回调函数每次都会传递一个数组索引和相应的数组值作为参数。本质上来说2个都是遍历,那么我们是不是要写2个方法呢?

我们来看看jQuery的源码:

jQuery.prototype = {
    each: function( callback, args ) {
        return jQuery.each( this, callback, args );
    }
}
var Newobj = function(name){
        this.name = name;
    }
   Newobj.showName = function(args){//静态方法:不能被实例对象调用
        console.log(args);
   }
   Newobj.prototype = {
        showName: function(args){//实例方法
            return Newobj.showName(this.name + args );
        }
   }
   var s = new Newobj("sss");
   s.showName("bbb");//sssbbb

实例方法取于静态方法,换句话来说这是静态与实例方法共享设计,静态方法挂在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

这段代码就是整个结构设计的最核心的东西了,有这样的一个处理,整个结构就活了!不得不佩服作者的设计思路,别具匠心。

看看init的的构造图:

(单击图片查看大图)

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

var $$ = ajQuery = function(selector) {    //把原型上的init作为构造器    return new ajQuery.fn.init( selector );}ajQuery.fn = ajQuery.prototype = {    name: ‘aaron‘,    init: function(selector) {        this.selector = selector;        return this;    },    constructor: ajQuery}ajQuery.fn.init.prototype = ajQuery.fn;ajQuery.fn.foo = function () { alert("foo!"); };ajQuery(".some-selector").foo();//挂在ajQuery.fn上的实例方法变成了ajQuery(ajQuery.fn.init)上的原型方法

http://stackoverflow.com/questions/1755080/why-jquery-do-this-jquery-fn-init-prototype-jquery-fn
时间: 2024-08-04 19:38:37

jQuery分离构造器的相关文章

【深入浅出jQuery】源码浅析2--奇技淫巧

最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐进增强)优雅的处理能力以及 Ajax 等方面周到而强大的定制功能无不令人惊叹. 另外,阅读源码让我接触到了大量底层的知识.对原生JS .框架设计.代码优化有了全新的认识,接下来将会写一系列关于 jQuery 解析的文章. 我在 github 上关于 jQuery 源码的全文注解,感兴趣的可以围观一下

【深入浅出jQuery】源码浅析--整体架构(转)

最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐进增强)优雅的处理能力以及 Ajax 等方面周到而强大的定制功能无不令人惊叹. 另外,阅读源码让我接触到了大量底层的知识.对原生JS .框架设计.代码优化有了全新的认识,接下来将会写一系列关于 jQuery 解析的文章. 我在 github 上关于 jQuery 源码的全文注解,感兴趣的可以围观一下

【深入浅出jQuery】源码浅析--整体架构

最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐进增强)优雅的处理能力以及 Ajax 等方面周到而强大的定制功能无不令人惊叹. 另外,阅读源码让我接触到了大量底层的知识.对原生JS .框架设计.代码优化有了全新的认识,接下来将会写一系列关于 jQuery 解析的文章. 我在 github 上关于 jQuery 源码的全文注解,感兴趣的可以围观一下

JQuery面向对象编程快速入门(八)-插件开发

JQuery源码片段分析 (function(window){ /** * jQuery是一个函数 是一个对象 是一个构造器函数 */ var jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context ); }, //fn就是jQuery对象上的一个属性,该属性指向了prototype //jQuery的 prototype中的方法是根据jQuery的选择器获取到的jQuery对象,

jQuery内核详解与实践读书笔记2:破解jQuery选择器接口1

前两篇已经介绍了如何搭建一个jQuery框架的雏形,从这一篇开始详细了解jQuery选择器的接口.jQuery选择器功能强大但用法很简单,它仅仅提供了一个接口:jQuery(),也可以简写为$(). 1. 简单但很复杂的黑洞 jQuery提供了唯一的接口(jQuery()或$())使选择器与外界进行交流.jQuery框架的基础是查询,即查询文档元素对象,因此可以认为jQuery对象就是一个选择器,并在此基础上构建和运行查询过滤器.jQuery查询结果的数据集合是jQuery对象的一部分.在$()

jquery源码学习(一)core部分

这一部分是jquery的核心 jquery的构造器 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 jQu

Vue.js比jQuery更好学

大家普遍认为,对于新手web程序员来说,jQuery被认为是一个好的入门点,甚至于很多程序员都是先学jQuery,再学原生Javascript. 为什么呢?首先是因为jQuery非常流行,但更重要的是,有经验的程序员都认为jQuery十分简单,推己及人,对于新手来说当然也应该是非常简单的,然而这并不正确. jQuery简洁,但不简单. jQuery绝对可以帮你处理掉很多老浏览器的麻烦事(译者注:比如各种兼容性问题),但对于简化DOM API操作和封装Javascript变化而言,它就帮不上什么忙

3、jQuery面向对象

1.首先介绍callback.js对ajax进行了封装 function ajaxFunction(){ var xmlHttp; try{ // Firefox, Opera 8.0+, Safari xmlHttp=new XMLHttpRequest(); } catch (e){ try{// Internet Explorer xmlHttp=new ActiveXObject("Msxml2.XMLHTTP"); } catch (e){ try{ xmlHttp=new

jQuery整体架构源码解析

最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐进增强)优雅的处理能力以及 Ajax 等方面周到而强大的定制功能无不令人惊叹. 另外,阅读源码让我接触到了大量底层的知识.对原生JS .框架设计.代码优化有了全新的认识,接下来将会写一系列关于 jQuery 解析的文章. 我在 github 上关于 jQuery 源码的全文注解,感兴趣的可以围观一下