jQuery.attr() 源码解读

我们知道,$().attr()实质上是内部调用了jQuery.access方法,在调用时jQuery.attr作为回调传入。在通过种种判断(参看jQuery.access()方法)之后,取值和赋值最后调用了这个jQuery.attr方法。

所以,关键是看jQuery.attr这里怎么走了~~

源码如下:

   attr: function( elem, name, value ) {
        var hooks, ret,
            nType = elem.nodeType;
        //如果elem不存在,或者是文本、注释、属性节点
        // don‘t get/set attributes on text, comment and attribute nodes
        if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
            return;
        }

        // Fallback to prop when attributes are not supported
        if ( typeof elem.getAttribute === core_strundefined ) {//如果elem不支持getAttribute 比如document或者文档碎片
            return jQuery.prop( elem, name, value );//调用jQuery.prop方法
        }

        // All attributes are lowercase
        // Grab necessary hook if one is defined
        //?
        if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {//elem不是标签或者elem不在xml中
            name = name.toLowerCase();//属性名大写
            hooks = jQuery.attrHooks[ name ] ||
                ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );//jQuery.attrHooks.type
        }

        if ( value !== undefined ) {//赋值

            if ( value === null ) {//如果设的值为null,相当于移除attr ,比如.attr(‘checked‘,null);
                jQuery.removeAttr( elem, name );

            } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {//调用钩子的set方法
                return ret;

            } else {
                elem.setAttribute( name, value + "" );//如果value是数值,隐式转为字符串
                return value;
            }

        } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {//调用钩子的get
            return ret;

        } else {//取值
            ret = jQuery.find.attr( elem, name );//调用Sizzle.attr  因为jquery中有一句:jQuery.find = Sizzle;
            //将null值修正为undefined
            // Non-existent attributes return null, we normalize to undefined
            return ret == null ?
                undefined :
                ret;
        }
    }

从上面的代码看,有7个走向:

1、return

2、jQuery.prop

3、jQuery.removeAttr

4、attrHooks.set

5、elem.setAttribute

6、attrHooks.get

7、Sizzle.attr

前面5个都是设置值,6和7是读值。

2和3以后会读到,这里不提,先看看Sizzle.attr中是怎么一回事吧^^

    Sizzle.attr = function( elem, name ) {
    // Set document vars if needed
    if ( ( elem.ownerDocument || elem ) !== document ) {//如果不是当前document
        setDocument( elem );//不知道干嘛 考虑iframe的情况?
    }

    //Expr.attrHandle是一个对象,包含了
    //async autofocus autoplay checked controls defer disabled hidden ismap loop
    //multiple open readonly required scoped selected 等自定义方法(属性)
    var fn = Expr.attrHandle[ name.toLowerCase() ],
        // Don‘t get fooled by Object.prototype properties (jQuery #13807)

        //hasOwn 就是hasOwnProperty
        //所以这个hasOwn.call( Expr.attrHandle, name.toLowerCase() ) 是在判断传入的属性名是不是这个对象的
        //自定义属性,而不是原型上的属性
        //val为调用自定义方法的结果或者undefined
        val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
            fn( elem, name, !documentIsHTML ) :
            undefined;

    //如果val为undefined
        //如果(support.attributes为真或者document不是html),返回elem.getAttribute( name )的值
        //否则 val为 elem.getAttributeNode(name))的值
            //如果val为真,并且val.specified为真,返回val.value
            //否则返回null
    //否则返回val
    return val === undefined ?
        support.attributes || !documentIsHTML ?
            elem.getAttribute( name ) :
            (val = elem.getAttributeNode(name)) && val.specified ?
                val.value :
                null :
        val;
};

复杂的三元运算符看得头都大了有木有,好吧,这里能看到,取值用getAttribute或者getAttributeNode。

再看attrHooks是一些什么内容:

    attrHooks: {
        type: {
            set: function( elem, value ) {
                if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
                    // Setting the type on a radio button after the value resets the value in IE6-9
                    // Reset value to default in case type is set after value during creationvar val = elem.value;
                    elem.setAttribute( "type", value );
                    if ( val ) {
                        elem.value = val;
                    }
                    return value;
                }
            }
        }
    }

从这里可以看到,attrHooks与设置input标签的type值有关,恩,如果设置的值为radio的时候,注意下。

时间: 2024-12-27 22:28:12

jQuery.attr() 源码解读的相关文章

jQuery toggleClass 源码解读

toggleClass: function( value, stateVal ) { var type = typeof value;//值类型 if ( typeof stateVal === "boolean" && type === "string" ) {//如果第二个参数为bool值 return stateVal ? this.addClass( value ) : this.removeClass( value );//如果第二个参为t

jQuery addClass() 源码解读

addClass: function( value ) { var classes, elem, cur, clazz, j, i = 0, len = this.length, proceed = typeof value === "string" && value; if ( jQuery.isFunction( value ) ) { return this.each(function( j ) { jQuery( this ).addClass( value.c

jquery offsetParent()源码解读

offsetParent: function() { return this.map(function() { var offsetParent = this.offsetParent || docElem; while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === &q

jQuery prop() 源码解读

prop: function( elem, name, value ) { var ret, hooks, notxml, nType = elem.nodeType; // don't get/set properties on text, comment and attribute nodes //标签不存在或者是文本.属性.注释节点 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return; } notxml =

jQuery position() 源码解读

position的代码比较简单... position: function() { if ( !this[ 0 ] ) { return; } var offsetParent, offset, elem = this[ 0 ], parentOffset = { top: 0, left: 0 }; // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only

jQuery.extend()源码解读

// extend方法为jQuery对象和init对象的prototype扩展方法// 同时具有独立的扩展普通对象的功能jQuery.extend = jQuery.fn.extend = function() { /* *target被扩展的对象 *length参数的数量 *deep是否深度操作 */ var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = ar

jQuery源码解读第5章---对Callbacks的解读

jQuery.Callbacks() 是一个多用途的回调函数列表对象 提供了一种强大的方法来管理回调函数队列 先来看看Callbacks的常见的用法 1-------不带参数 先看看不用回调函数的例子 eq function a1(){ console.log('a1') } (function(){ function a2(){ console.log('a2') } })() a1() // a1 a2() //就不行了 这时候我们就可以使用回调函数Callbacks 了 var dfd1

jQuery源码解读第4章---对extend的解读

为什么我们一开始就说extend呢 其实我读源码的过程中,发现其实我们方法就在源码中都调用了extend Callbacks Deferred这些工具方法 所以我们很有必要先学习这些,,,,,,,,,,,这样对我们后续的学习很有帮助 对extend的学习,,,,,首先看下extend我们平时是怎么用的 1...合并对象 extend(dest,src1,src2,,,,,) 它的含义就是将src1,src2......合并到dest中 然后放回的结果就是合并后的dest eq: var dest

jQuery.attributes源码分析(attr/prop/val/class)

回顾 有了之前的几篇对于jQuery.attributes相关的研究,是时候分析jQuery.attr的源码了 Javascript中的attribute和property分析 attribute和property兼容性分析 jQuery.access源码分析 结构 jQuery.fn.extend({ attr: function (name, value) { }, removeAttr: function (name) { }, prop: function (name, value) {