zoukankan      html  css  js  c++  java
  • jQuery构造函数init参数分析(一)

          在我的上一篇随笔里面分析了jQuery的构造函数,jQuery对象中有一个原型方法init才是是真正的构造函数,通过init的原型对象跟jQuery的原型对象保持引用关系使得init的实例可以正常调用jQuery的原型方法,就好像是jQuery的实例一样。下面就来看看init这个幕后的构造函数是怎么写的:

    init: function( selector, context, rootjQuery ) {
    
    ...
    
    }

    可以看到这个方法接受3个参数,其前两个参数是jQuery方法传递过来的

    var jQuery = function( selector, context ) {
    
    // The jQuery object is actually just the init constructor 'enhanced'
    
    return new jQuery.fn.init( selector, context, rootjQuery );
    
    },

    Selector原则上可以输入任意值,但并不是所有值都是有意义的,只有undefinedDOM 元素、字符串、函数、jQuery 对象、普通 JavaScript 对象这几种类型是有效的,这个参数是通常是填写的但是不填写也不会报错

    console.log($());
    
    //[constructor: function, init: function, selector: "", jquery: "1.7.1", size: function…]

    Context作为执行上下文或者叫执行范围可以不传入,或者传入 DOM 元素、jQuery 对象、普通 JavaScript 对象之一

    参数 rootjQuery:包含了 document 对象的 jQuery 对象,用于 document.getElementById() 查找失败、selector 是选择器表达式且未指定 contextselector 是函数的情况,其实就是$(document)

    下面根据参数的不同分为12种情况逐个讨论

    1.selector 可以转换为false

    // Handle $(""), $(null), or $(undefined)
    
    if ( !selector ) {
    
    return this;
    
    }

    源码中的注释已经写得很清楚了,当是这三种情况时直接return不进行任何处理

    2.参数 selector 是 DOM 元素

    例如: $(document)这种写法

    // Handle $(DOMElement)
    
    if ( selector.nodeType ) {
    
    this.context = this[0] = selector;
    
    this.length = 1;
    
    return this;
    
    }

    只要是dom元素肯定有节点类型,然后把这个节点变成jquery对象的第一个元素并且赋值给上下文context,length属性是jQuery的原型属性默认为0

    // The default length of a jQuery object is 0
    
    length: 0,

    这里有了一个元素之后就把length属性修改为1return this 操作使得函数执行后的结果依然是jQuery对象这样就可以实现类似$(document).each()这样的链式调用了。最终得到的类似这样的{0:document,context:document,length:1....}对象,其实所有的情况最后都会变成这种形式的对象,除了jQuery原型属性和方法之外就是获取的dom节点并且按照阿拉伯数字依次排列,所以我们可以使用$(selector)[0]的形式代替$(selector).get(0)来获取dom对象。例如:

    <!doctype html>
    
    <html>
    
       <head>
    
          <title></title>
    
       </head>
    
       <body>
    
           <div></div>
    
           <div></div>
    
           <div></div>
    
       </body>
    
       <script src='jquery-1.7.1.js'></script>
    
       <script>
    
         console.log($('div'));
    
    /*[div, div, div, prevObject: jQuery.fn.jQuery.init[1], context: document, selector: "div", constructor: function, init: function…]
    
    0: div
    1: div
    2: div
    context: document
    length: 3
    prevObject: jQuery.fn.jQuery.init[1]__proto__: jQuery[0]
    selector: "div"
    .
    */
       </script>
    
    </html>

    3.参数是特殊的字符串“body

    由于body元素在一个文档对象中只有一个所以单独列出来处理

    // The body element only exists once, optimize finding it
    
    if ( selector === "body" && !context && document.body ) {
    
    this.context = document;
    
    this[0] = document.body;
    
    this.selector = selector;
    
    this.length = 1;
    
    return this;
    
    }

    这里有3个条件必须同时满足,第二个必须没有上下文的条件我也不是太理解,$(‘body’,document)这样的看起来很正常的写法也会被这种情况“忽视”     

     console.log($('body',document));
    
     /*
    
     jQuery.fn.jQuery.init[1]
    
    0: body
    
    context: document
    
    length: 1
    
    prevObject: jQuery.fn.jQuery.init[1]
    
    selector: "body"
    
    __proto__: jQuery[0]
    
    */

    虽然和$('body')的结果是一样的,但是却被当做两种情况来看待,可能是因为body只有一个上下文只能是document没有必要添加吧,否则又要判断上下文是不是document。第三个条件是保证document.body必须存在,那么什么情况下会前两个情况满足document.body又不存在呢?首先就是js代码先于html代码加载时会出现这个是初学者经常会犯的错误,通常我们要写成:

    $(function(){...})

    或者

    $(document).ready(function(){...})

    其实这两个是一样的调取的是一个方法,dom加载这一块以后在分析。对此我们可以做个测试html代码如下:

    <!doctype html>
    
    <html>
    
       <head>
    
          <title></title>
    
            <script src='jquery-1.7.1.js'></script>
    
          <script> 
    
                  $('body')
    
       </script>
    
       </head>
    
       <body>
    
           <div></div>
    
           <div></div>
    
           <div></div>
    
       </body>
    
    </html>
    

      

    然后再jQuery源代码里面输出selectorcontextdocument.body

     

    console.log(selector+context+document.body);
    
    // The body element only exists once, optimize finding it
    
    if ( selector === "body" && !context && document.body ) {
    
    this.context = document;
    
    this[0] = document.body;
    
    this.selector = selector;
    
    this.length = 1;
    
    return this;
    
    }

    虽然我们只写了一个其实执行了四次,只有最后一次才是是我们调用后的结果,最后一次的结果是bodyundefinednull这个时候前两个就是满足的但是最后一个是null。回想起第一篇jQuery总体架构架构里面undefined会被重新,那么document.body会不会被重写为null呢?当我尝试在代码中修改时就会报错看来是不会的,那这个条件就是预防没有加载html就执行的情况吧

    第四种是除了上述的字符串情况之外的其他字符串,情况比较多放在下一篇吧。

     

  • 相关阅读:
    写代码的方法与思考
    改变文件上传input file类型的外观
    关于HTML Button点击自动刷新页面的问题解决
    使用 git push 出现error setting certificate verify locations问题记录
    flex使用学习
    jQuery.fn.extend()
    jQuery extend()
    作用域
    私有变量
    模仿块级作用域
  • 原文地址:https://www.cnblogs.com/yy-hh/p/4495470.html
Copyright © 2011-2022 走看看