这里只介绍这几个方法的源码,这部分引用了一个技巧,钩子对象,用来做兼容fixed的对象,后面也有一些使用。钩子对象具体的兼容细节这里就不详解了。

 var nodeHook, boolHook,
rclass = /[\t\r\n]/g,
rreturn = /\r/g,
rfocusable = /^(?:input|select|textarea|button|object)$/i,
rclickable = /^(?:a|area)$/i,
rboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,
ruseDefault = /^(?:checked|selected)$/i,
getSetAttribute = jQuery.support.getSetAttribute,
getSetInput = jQuery.support.input; jQuery.fn.extend({
attr: function (name, value) {
return jQuery.access(this, jQuery.attr, name, value, arguments.length > 1);
},
removeAttr: function (name) {
return this.each(function () {
jQuery.removeAttr(this, name);
});
},
prop: function (name, value) {
return jQuery.access(this, jQuery.prop, name, value, arguments.length > 1);
},
removeProp: function (name) {
name = jQuery.propFix[ name ] || name;
return this.each(function () {
// try/catch handles cases where IE balks (such as removing a property on window)
try {
this[ name ] = undefined;
delete this[ name ];
} catch (e) {
}
});
},
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.call(this, j, this.className));
});
} if (proceed) {
// The disjunction here is for better compressibility (see removeClass)
classes = ( value || "" ).match(core_rnotwhite) || []; for (; i < len; i++) {
elem = this[ i ];
cur = elem.nodeType === 1 && ( elem.className ?
( " " + elem.className + " " ).replace(rclass, " ") :
" "
); if (cur) {
j = 0;
while ((clazz = classes[j++])) {
if (cur.indexOf(" " + clazz + " ") < 0) {
cur += clazz + " ";
}
}
elem.className = jQuery.trim(cur); }
}
} return this;
},
removeClass: function (value) {
var classes, elem, cur, clazz, j,
i = 0,
len = this.length,
proceed = arguments.length === 0 || typeof value === "string" && value; if (jQuery.isFunction(value)) {
return this.each(function (j) {
jQuery(this).removeClass(value.call(this, j, this.className));
});
}
if (proceed) {
classes = ( value || "" ).match(core_rnotwhite) || []; for (; i < len; i++) {
elem = this[ i ];
// This expression is here for better compressibility (see addClass)
cur = elem.nodeType === 1 && ( elem.className ?
( " " + elem.className + " " ).replace(rclass, " ") :
""
); if (cur) {
j = 0;
while ((clazz = classes[j++])) {
// Remove *all* instances
while (cur.indexOf(" " + clazz + " ") >= 0) {
cur = cur.replace(" " + clazz + " ", " ");
}
}
elem.className = value ? jQuery.trim(cur) : "";
}
}
} return this;
},
toggleClass: function (value, stateVal) {
var type = typeof value,
isBool = typeof stateVal === "boolean"; if (jQuery.isFunction(value)) {
return this.each(function (i) {
jQuery(this).toggleClass(value.call(this, i, this.className, stateVal), stateVal);
});
} return this.each(function () {
if (type === "string") {
// toggle individual class names
var className,
i = 0,
self = jQuery(this),
state = stateVal,
classNames = value.match(core_rnotwhite) || []; while ((className = classNames[ i++ ])) {
// check each className given, space separated list
state = isBool ? state : !self.hasClass(className);
self[ state ? "addClass" : "removeClass" ](className);
} // Toggle whole class name
} else if (type === core_strundefined || type === "boolean") {
if (this.className) {
// store className if set
jQuery._data(this, "__className__", this.className);
} // If the element has a class name or if we're passed "false",
// then remove the whole classname (if there was one, the above saved it).
// Otherwise bring back whatever was previously saved (if anything),
// falling back to the empty string if nothing was stored.
this.className = this.className || value === false ? "" : jQuery._data(this, "__className__") || "";
}
});
},
hasClass: function (selector) {
var className = " " + selector + " ",
i = 0,
l = this.length;
for (; i < l; i++) {
if (this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf(className) >= 0) {
return true;
}
} return false;
},
val: function (value) {
var ret, hooks, isFunction,
// 获取伪数组中的第一个元素
elem = this[0]; // 如果没有传参,说明是获取value值
if (!arguments.length) {
if (elem) {
// 尝试获取valHooks钩子对象,
// 如果元素不具有type类型的钩子对象,
// 则尝试赋值元素标签键值的钩子对象
hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; // 如果存在钩子对象且有get方法且get返回的不是undefined
// 则返回get方法的返回值
if (hooks && "get" in hooks && (ret = hooks.get(elem, "value")) !== undefined) {
return ret;
} // 否则没有相应的钩子对象,直接获取元素的value值
ret = elem.value; // 如果ret是字符串,返回过滤掉制表符的字符串,
// 否则ret为空就返回空字符串,
// 否则返回ret
return typeof ret === "string" ?
// handle most common string cases
ret.replace(rreturn, "") :
ret == null ? "" : ret;
} return;
} // 下面是有参数的情况,说明是设置value值 // 先判断value是否为函数
isFunction = jQuery.isFunction(value); // 遍历元素集
return this.each(function (i) {
var val,
self = jQuery(this); if (this.nodeType !== 1) {
return;
} // 如果value是函数就执行,然后给ret赋值返回的值
if (isFunction) {
val = value.call(this, i, self.val());
} else {
val = value;
} // 如果value为null或undefined,转化为字符串
// 如果是数字类型也转换为字符串
// 如果是数组类型,使用map方法返回一个返回值数组
if (val == null) {
val = "";
} else if (typeof val === "number") {
val += "";
} else if (jQuery.isArray(val)) {
val = jQuery.map(val, function (value) {
return value == null ? "" : value + "";
});
} // 尝试获取钩子对象
hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; // 如果没有钩子对象,或者钩子对象没有set方法,
// 又或者set方法返回的值是undefined,
// 就使用正常操作
if (!hooks || !("set" in hooks) || hooks.set(this, val, "value") === undefined) {
this.value = val;
}
});
}
}); jQuery.extend({
valHooks: {
option: {
/*
获取option的value值
*/
get: function (elem) {
// Blackberry 4.7的attributes.value为undefined但可以使用.value获取
var val = elem.attributes.value;
return !val || val.specified ? elem.value : elem.text;
}
},
/* 获取select的value值,如果是多选则返回数组 */
select: {
get: function (elem) {
var value, option,
options = elem.options,
index = elem.selectedIndex,
one = elem.type === 'select-one' || index < 0,
values = one ? null : [],
max = one ? index + 1 : options.length,
i = index < 0 ? max :
one ? index : 0; // 遍历所有选中的项
for (; i < max; i++) {
option = options[i]; // 旧版本IE不会更新选中项当表单重置后
if ((option.selected || i === index) &&
// 不返回被禁用的选项或者在被禁用的optgroup中
(jQuery.support.optDisabled ? !option.disabled : option.getAttribute('disabled') === null) &&
(!option.parentNode.disabled || !jQuery.nodeName(option.parentNode, 'optgroup'))
) {
// 为option设置指定值
value = jQuery(option).val(); // 单选的话我们就不需要用数组了
if (one) {
return value;
} // 多选就返回数组
values.push(value);
}
} return values;
},
set: function (elem, value) {
var values = jQuery.makeArray(value); jQuery(elem).find('option').each(function () {
this.selected = jQuery.inArray(jQuery(this).val(), values) >= 0;
}); if (!values.length) {
elem.selectedIndex = -1;
}
return values;
}
}
},
attr: function (elem, name, value) {
var hooks, notxml, ret,
nType = elem.nodeType; // 如果elem的类型是文本,注释或者属性直接退出
if (!elem || nType === 3 || nType === 8 || nType === 2) {
return;
} // 当不支持attributes时,回退用prop方法
if (typeof elem.getAttribute === core_strundefined) {
return jQuery.prop(elem, name, value);
} // 是否非XML文档
notxml = nType !== 1 || !jQuery.isXMLDoc(elem); // 如果钩子被定义了则抓取
if (notxml) {
name = name.toLowerCase();
// 如果不存在attrHooks钩子对象就尝试获取boolHook的钩子对象,
// 否则就用nodeHook这个钩子对象
hooks = jQuery.attrHooks[name] || (rboolean.test(name) ? boolHook : nodeHook);
} if (value !== undefined) {
// value为null就删除attr属性
if (value === null) {
jQuery.removeAttr(elem, name);
} else if (hooks && notxml && 'set' in hooks && (ret = hooks.set(elem, value, name)) !== undefined) {
// 否则如果存在钩子方法,则返回set方法的返回值
return ret;
} else {
// 其他情况就直接用setAttribute设置value
elem.setAttribute(name, value + '');
}
} else if (hooks && notxml && 'get' in hooks && (ret = hooks.get(elem, name)) !== null) {
// 如果value是undefined,且存在钩子方法,
// 返回get方法的返回值
return ret;
} else {
// 其他情况(无钩子对象)就使用getAttribute获取value
// 在IE9+,Flash对象没有.getAttribute
if (typeof elem.getAttribute !== core_strundefined) {
ret = elem.getAttribute(name); return ret == null ?
undefined :
ret;
}
}
},
removeAttr: function (elem, value) {
var name, propName,
i = 0,
// value值可以是空格连接的多个value,
// 这里通过正则匹配非空字符串,返回匹配的数组
attrNames = value && value.match(core_rnotwhite); // 如果attrNames存在且elem是元素节点
if (attrNames && elem.nodeType === 1) {
// 遍历attrNames数组
while ((name = attrNames[i++])) {
// 如果没有propFix对象(将name转换为正确的字符串)就直接使用name作为属性值
propName = jQuery.propFix[name] || name; // 布尔值的属性需要特殊处理
if (rboolean.test(name)) {
// 如果不支持获取和设置属性且有selected或checked属性,
// 则将defaultName和propName设置为false
if (!getSetAttribute && ruseDefault.test(name)) {
elem[jQuery.camelCase('default-' + name)] = elem[propName] = false;
} else {
// 其他情况直接把propName属性设置为false
elem[propName] = false;
}
} else {
// 非布尔值属性就调用jQuery.attr方法
jQuery.attr(elem, name, '');
} // 删除元素上的该属性
elem.removeAttribute(getSetAttribute ? name : propName);
}
}
},
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 creation
var val = elem.value;
elem.setAttribute('type', value);
if (val) {
elem.value = val;
}
return value;
}
}
}
},
propFix: {
tabindex: 'tabIndex',
readonly: 'readOnly',
'for': 'htmlFor',
'class': 'className',
maxlength: 'maxLength',
cellspacing: 'cellSpacing',
cellpadding: 'cellPadding',
rowspan: 'rowSpan',
colspan: 'colSpan',
usemap: 'useMap',
frameborder: 'frameBorder',
contenteditable: 'contentEditable'
},
prop: function (elem, name, value) {
var ret, hooks, notxml,
nType = elem.nodeType; if (!elem || nType === 3 || nType === 8 || nType === 2) {
return;
} notxml = nType !== 1 || !jQuery.isXMLDoc(elem); // 如果elem不是xml文档元素,获取被fixed的name和钩子对象
if (notxml) {
name = jQuery.propFix[name] || name;
hooks = jQuery.propHooks[name];
} // 如果value不是undefined,说明是设置prop
if (value !== undefined) {
// 如果有钩子对象且存在set方法,
// 返回非undefined的方法返回值,
// 否则正常情况下直接用elem[name]设置prop
if (hooks && 'set' in hooks && (ret = hooks.set(elem, value, name)) !== undefined) {
return ret;
} else {
return (elem[name] = value);
} // 如果value是undefined,说明是获取prop属性值
} else {
// 有钩子对象用其get方法,没有就用原生的方法
if (hooks && 'get' in hooks && (ret = hooks.get(elem, name)) !== null) {
return ret;
} else {
return elem[name];
}
}
},
propHooks: {
tabIndex: {
get: function (elem) {
// 当elem的tabindex没有被明确设置时,不会总返回正确的值
var attributeNode = elem.getAttributeNode('tabindex'); return attributeNode && attributeNode.specified ?
parseInt(attributeNode.value, 10) :
rfocusable.test(elem.nodeName) || rclickable.test(elem.nodeName) && elem.href ?
0 :
undefined;
}
}
}
}); // Hook for boolean attributes
boolHook = {
get: function (elem, name) {
var
// Use .prop to determine if this attribute is understood as boolean
prop = jQuery.prop(elem, name), // Fetch it accordingly
attr = typeof prop === "boolean" && elem.getAttribute(name),
detail = typeof prop === "boolean" ? getSetInput && getSetAttribute ?
attr != null :
// oldIE fabricates an empty string for missing boolean attributes
// and conflates checked/selected into attroperties
ruseDefault.test(name) ?
elem[ jQuery.camelCase("default-" + name) ] :
!!attr : // fetch an attribute node for properties not recognized as boolean
elem.getAttributeNode(name); return detail && detail.value !== false ?
name.toLowerCase() :
undefined;
},
set: function (elem, value, name) {
if (value === false) {
// Remove boolean attributes when set to false
jQuery.removeAttr(elem, name);
} else if (getSetInput && getSetAttribute || !ruseDefault.test(name)) {
// IE<8 needs the *property* name
elem.setAttribute(!getSetAttribute && jQuery.propFix[ name ] || name, name); // Use defaultChecked and defaultSelected for oldIE
} else {
elem[ jQuery.camelCase("default-" + name) ] = elem[ name ] = true;
} return name;
}
};

jQuery1.9.1--attr,prop与val方法源码分析的更多相关文章

  1. Java split方法源码分析

    Java split方法源码分析 public String[] split(CharSequence input [, int limit]) { int index = 0; // 指针 bool ...

  2. invalidate和requestLayout方法源码分析

    invalidate方法源码分析 在之前分析View的绘制流程中,最后都有调用一个叫invalidate的方法,这个方法是啥玩意?我们来看一下View类中invalidate系列方法的源码(ViewG ...

  3. Linq分组操作之GroupBy,GroupJoin扩展方法源码分析

    Linq分组操作之GroupBy,GroupJoin扩展方法源码分析 一. GroupBy 解释: 根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值. 查询表达式: var ...

  4. jQuery.extend()方法和jQuery.fn.extend()方法源码分析

    这两个方法用的是相同的代码,一个用于给jQuery对象或者普通对象合并属性和方法一个是针对jQuery对象的实例,对于基本用法举几个例子: html代码如下: <!doctype html> ...

  5. jQuery实现DOM加载方法源码分析

    传统的判断dom加载的方法 使用 dom0级 onload事件来进行触发所有浏览器都支持在最初是很流行的写法 我们都熟悉这种写法: window.onload=function(){ ... }  但 ...

  6. jQuery.clean()方法源码分析(一)

    在jQuery 1.7.1中调用jQuery.clean()方法的地方有三处,第一次就是在我之前的随笔分析jQuery.buildFramgment()方法里面的,其实还是构造函数的一部分,在处理诸如 ...

  7. 【Java】NIO中Selector的select方法源码分析

    该篇博客的有些内容和在之前介绍过了,在这里再次涉及到的就不详细说了,如果有不理解请看[Java]NIO中Channel的注册源码分析, [Java]NIO中Selector的创建源码分析 Select ...

  8. python-django rest framework框架之dispatch方法源码分析

    1.Django的 CBV 中在请求到来之后,都要执行dispatch方法,dispatch方法根据请求方式不同触发 get/post/put等方法 class APIView(View): def ...

  9. hashCode()方法源码分析

    执行代码 public class Demo06 { public static void main(String[] args) { String s="hello"; Syst ...

随机推荐

  1. 第八章 管理类型(In .net4.5) 之 加强封装

    1. 概述 本章内容包括 访问控制符.属性 和 显式接口实现. 2. 主要内容 2.1 访问控制符 封装的核心是隐藏信息.访问控制符用来实现类型成员的访问控制. C#的访问控制符有:public, i ...

  2. 实战Django:官方实例Part1

    [写在前面] 撰写这个实战系列的Django文章,是很久之前就有的想法,问题是手头实例太少,一旦开讲,恐有"无米下锅"之忧. 随着对Django学习的深入,渐渐有了些心得,把这些心 ...

  3. R语言将数据框转成xts

    R语言初学者,不怎么会,今天碰到的问题,查了好久才找到,原来如此简单 尼玛,下次再忘记抽自己3巴掌

  4. 实习感悟——SQL语句

    在这次实习中用到了很多SQL语句,下面就给大家分享分享: 1.group by 字面意思我们一看就知道groupby通过分组的意思,通过数据库某个字段的分组我们可以做什么?联系到生活中,我们给一组对象 ...

  5. 019C#中使用移位运算符获取汉字编码值

    在进行移位运算时,当数值的二进制数每次向左移1位就相当于乘以2,当数值每次向右移一位就相当于除以2 private void button1_Click(object sender, EventArg ...

  6. Java之NIO传输数据

    NIO可谓陈词旧调,不值一提. 但之前都是泛泛而谈, 现在深入应用才知道秘诀所在. 对于SocketChannel有read()与write(),但由于"非阻塞IO"本质, 这二个 ...

  7. 无法产生coredump的问题

    我写了一个必然会崩溃的程序,名字为 test :#include "stdlib.h"#include "unistd.h" int main(){ char ...

  8. CoreLocation简单应用

    1.获取locationManager let locationManager: CLLocationManager = CLLocationManager() 2.设置locationManager ...

  9. 微软职位内部推荐-Software Engineer II-SDP

    微软近期Open的职位: Position: SDE II The R&D of Shared Data Platform at Application and Services Group ...

  10. js event bubble and capturing

    Bubble: pppppp Capturing pppppp Mix pppppp To Stop Bubble pppppp // JS Bin