zoukankan      html  css  js  c++  java
  • javascript 点点滴滴 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构造器的原型对象,因为是引用传递所以不需要担心这个循环引用的性能问题。

    */
     
     
     
     
                                                      (代码出自艾伦大大大大)
  • 相关阅读:
    Intern Day7
    Intern Day7
    Intern Day7
    Intern Day6
    Intern Day6
    Intern Day6
    Intern Day6
    Intern Day6
    萧萧远树疏林外,一半秋山带夕阳
    飞线
  • 原文地址:https://www.cnblogs.com/hfdj/p/7591151.html
Copyright © 2011-2022 走看看