jQuery晦涩的底层工具方法们

这里整理的是jQuery源码中一些比较晦涩难懂的、内部的、最底层的工具方法,它们多为jQuery的上层api方法服务,目前包括:

  • jQuery.access

jQuery.access: function( elems, fn, key, value, chainable, emptyGet, pass )

在jQuery的众多api方法中,许多方法都有一个非常重要和常见的特征:重载,简单来讲即参数的不同决定了方法的功能不同

例如我们最常使用的几个:jQuery.fn.val()、jQuery.fn.html()、jQuery.fn.attr()、jQuery.fn.text()、jQuery.fn.css()等等

从这些方法的身上,我们其实可以总结出它们之间一些共同具有的特征:

  • 所有的操作都是在元素节点上
  • 进行的操作都是get或set
  • 都有自己的处理函数
  • 都可以接受函数作为参数干预最终的结果
  • 具备链式调用的能力

源码解析:

// Multifunctional method to get and set values of a collection
// The value/s can optionally be executed if it‘s a function
/** 参数说明
  * elems [object] 元素
  * fn [function] 原始处理函数
  * key [string|object] 属性名称/键值对列表
  * value [type|function] 进行赋值的值/干预函数
  * chainable [boolean] 是否可以链式调用
  * emptyGet [type] 指定的空值,类型不定
  * pass [boolean] 属性与jQuery方法同名时,是否调用jQuery的方法,在attr方法那里会用到
*/
access: function( elems, fn, key, value, chainable, emptyGet, pass ) {
    var exec,
        bulk = key == null,
        i = 0,
        length = elems.length;

    // Sets many values
    // 如果key是一个键值对对象,那么一定是在赋值,分解key然后递归调用
    if ( key && typeof key === "object" ) {
        for ( i in key ) {
            // 可以看出,赋值操作都是可以继续链式调用,因为chainable直接被赋值为了1
            jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );
        }

        // 这里仍然需要手动设置chainable的值为1
        // 因为这里并没有return
        chainable = 1;

    // Sets one value
    } else if ( value !== undefined ) {
        // Optionally, function values get executed if exec is true
        // 如果没传pass并且传入了干预函数
        exec = pass === undefined && jQuery.isFunction( value );

        // bulk = key == null
        // 即没有传入key,但传了value进来
        if ( bulk ) {
            // Bulk operations only iterate when executing function values
            // value是个函数的情况
            if ( exec ) {
                // 原始处理函数用exec保存起来
                exec = fn;
                // 把原本保存原始处理函数的变量fn重新用约定好的结构进行封装,以便后面统一进行调用
                // 这里的key参数纯粹是为了在后面的调用处统一参数
                // 注意这里的fn函数最后返回了原始处理函数的处理结果,为什么这样做呢?后面解释
                fn = function( elem, key, value ) {
                    return exec.call( jQuery( elem ), value );
                };

            // Otherwise they run against the entire set
            } else {
                // 这是最简单的情况,直接调用原始处理函数进行赋值
                // 这种情况下的赋值操作到这里就已经完成了
                // 所以在这里把fn置为了null,因为后面的if已经没有必要执行了
                fn.call( elems, value );
                fn = null;
            }
        }

        // 剔除上面最简单那种情况,无论传不传key的值,这里的if都会执行
        if ( fn ) {
            for (; i < length; i++ ) {
                // 这里的fn的值包含两种情况,一个是原始处理函数,一个是上面已经封装过的fn
                // 这里最难理解的应该就是fn( elems[i], key )这句话了
                // 首先无论是哪种情况,fn( elems[i], key )这句话一定是一个取值的操作
                // 那么如果fn是原始处理函数,并且传入了key的值,取到的其实就是这个元素的原始属性值,把它作为第二个参数传入了干预函数( $("div").attr( "id", function( index, attr ){} ) )
                // 如果fn是上面封装的函数,表示没有传入key值,则fn中的key和value都是undefined,但仍然仅凭元素就可以取得这个元素的原始属性值,哪种情况呢?如$("div").val("something")、$("div").text("something")
                // 所以,fn( elems[i], key )这句话的作用也就清晰了,就是取得元素的原始属性值
                // 搞懂了上面,这行代码也就不难理解了,这里设计的确实是巧啊
                fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
            }
        }

        // 同样,仍然是可以链式调用
        chainable = 1;
    }

    // 如果可以链式调用,返回元素集即可,函数到此结束
    // 如果不是,则证明是在取值
    // 如果没传key,直接返回fn.call( elems ),如$("div").val()
    // 如果传了key,则返回第一个元素的key对应的属性值或返回指定的空值emptyGet
    return chainable ?
        elems :

        // Gets
        bulk ?
            fn.call( elems ) :
            length ? fn( elems[0], key ) : emptyGet;
}

  

时间: 2024-12-29 01:24:51

jQuery晦涩的底层工具方法们的相关文章

jquery源码之工具方法

jQuery 作为时下前端的"霸主".它的强大已毋庸置疑.简洁,效率,优雅,易用等优点让人很容易对它珍爱有加. 作为js的小菜,为了提升自我等级,根据各大神博客精辟的解析,硬啃了jQuery源码.在此,并不是要解析啥源码啥的(也没到那个级别哈),读书笔记,仅此而已. 所谓磨刀不误砍柴功,jQuery在大展神通之前也做了许多准备工作.比如说他的一些工具方法: 首当其冲的是他的继承扩展方法: jQuery.extend 其实也不是传统意义的继承,说mixin可能更恰当一些. // 首先看看

JavaScript1.6数组新特性和JQuery的几个工具方法

JavaScript 1.6 引入了几个新的Array 方法,具体的介绍见:New in JavaScript 1.6.这些方法已经被写进了ECMA262 V5.现代浏览器(IE9/Firefox/Safari/Chrome/Opera)都已经支持,但IE6/7/8不支持.jquery的工具方法中提供了类似的功能. 1.Array.forEach()和jquery的$().each().在数组中的每个项上运行一个函数.类似java5 增强的for循环. 1 2 3 4 5 6 7 8 9 var

jQuery操作数组的工具方法

1.前言 很多时候,jQuery的$()函数都返回一个类似数组的jQuery对象,例如$("div")将返回由页面中所有<div-/>元素包装成jQuery对象,这个jQuery对象实际上包含了多个<div-/>元素对应的DOM对象.在这种情况下,jQuery提供了以下几个常用属性和方法来操作类数组的jQuery对象. 1)        length:该属性返回jQuery里包含的DOM元素的个数 2)        context:该属性返回获取jQuery

jquery源码解析:jQuery工具方法详解1

jQuery的工具方法,其实就是静态方法,源码里面就是通过extend方法,把这些工具方法添加给jQuery构造函数的. jQuery.extend({       //当只有一个对象时,就把这个对象中的属性和方法扩展到this对象中,这里的this指向jQuery expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ), //唯一性,core_version 为jQuery

jquery源码解析:jQuery延迟对象Deferred(工具方法)详解1

请先看上一课的回调对象.Deferred是通过extend添加到jQuery中的工具方法.如下所示: jQuery.extend({ Deferred: function( func ) { }, when: function( subordinate /* , ..., subordinateN */ ) { }}); 首先,来介绍下Deferred的使用: var cb = $.Deferred(); setTimeout(function(){ alert(1); cb.resolve()

jquery源码解析:jQuery工具方法详解2

jQuery的工具方法,其实就是静态方法,源码里面就是通过extend方法,把这些工具方法添加给jQuery构造函数的. jQuery.extend({ ...... type: function( obj ) {    //$.type(),判断类型 if ( obj == null ) {   //null,undefined return String( obj );    //返回null,undefined字符串 }     //core_toString = {}.toString 

jQuery常用工具方法

前面的话 jQuery提供一些与元素无关的工具方法,不必选中元素,就可以直接使用这些方法.如果理解原生javascript的继承原理,那么就能理解工具方法的实质.它是定义在jQuery构造函数上的方法,即jQuery.method(),所以可以直接使用.而那些操作元素的方法,是定义在构造函数的prototype对象上的方法,即jQuery.prototype.method(),所以必须生成实例(即选中元素)后使用.把工具方法理解成像javascript原生函数那样可以直接使用的方法就行了.下面将

jquery源码解析:jQuery工具方法详解3

jQuery的工具方法,其实就是静态方法,源码里面就是通过extend方法,把这些工具方法添加给jQuery构造函数的. jQuery.extend({ ...... each: function( obj, callback, args ) {   //$.each(arr , function(i,value){}),第三个参数用于内部调用.此方法就是来遍历数组的,然后取数组中的值进行显示.不能改变原数组arr,跟map一样,但是map返回新数组,而each返回原数组.这里跟原生的forEa

Java程序员的JavaScript学习笔记(9—— jQuery工具方法)

计划按如下顺序完成这篇笔记: 1.    理念. 2.    属性复制和继承. 3.    this/call/apply. 4.    闭包/getter/setter. 5.    prototype. 6.    面向对象模拟. 7.    jQuery基本机制. 8.    jQuery选择器. 9.    jQuery工具方法. 10.    jQuery-在"类"层面扩展. 11.    jQuery-在"对象"层面扩展. 12.    jQuery-扩