val: function( value ) {
var hooks, ret, isFunction,
elem = this[0]; if ( !arguments.length ) {//无参数
if ( elem ) {//第一个元素
//考虑元素是checkbox,radio,option或者select的情况,这时有val钩子
hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
//如果钩子存在且有get 且获取的值不为undefined,返回该值
if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
return ret;
}
//否则,ret就是元素的value
ret = elem.value;
//如果值是字符串
return typeof ret === "string" ?
//将换行符替换为""
ret.replace(rreturn, "") :
// 如果值不是字符串,考虑null和undefined的情况,如果是null或undefined,ret置为""
ret == null ? "" : ret;
} return;
}
//判断传入的参数value是否是函数
isFunction = jQuery.isFunction( value );
//遍历设值
return this.each(function( i ) {
var val; if ( this.nodeType !== 1 ) {//如果不是元素节点,返回
return;
} if ( isFunction ) {//如果是函数 函数的参数第一个是索引,第二个是对应的值
val = value.call( this, i, jQuery( this ).val() );
} else {
val = value;
} //如果val是null或者undefined,设为""
if ( val == null ) {
val = "";
//如果val是数字,转为字符串
} else if ( typeof val === "number" ) {
val += "";
//如果val是数组
} else if ( jQuery.isArray( val ) ) {//处理数组中的undefined null 和数字
val = jQuery.map( val, function( value ) {
return value == null ? "" : value + "";
});
}
//同样地,考虑元素是checkbox,radio,option或者select的情况
hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; // 如果set返回了undefined,回退到正常值val
if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
this.value = val;
}
});
}

valHooks:

jQuery.extend({
valHooks: {
option: {
get: function( elem ) {
//调用Sizzle.attr方法
var val = jQuery.find.attr( elem, "value" );
//如果val为null或undefined,取elem的text值
return val != null ?
val :
// Support: IE10-11+
// option.text throws exceptions (#14686, #14858)
jQuery.trim( jQuery.text( elem ) );
}
},
select: {
get: function( elem ) {
var value, option,
options = elem.options,
index = elem.selectedIndex,//当前选中项 单选默认0,多选默认-1
//如果是单选下拉框或者当前没有选中项,one为true
one = elem.type === "select-one" || index < 0,
values = one ? null : [],//one为true,则values为null,否则为[]
max = one ? index + 1 : options.length,//单选最大为1,多选为options.length
i = index < 0 ?
max :
one ? index : 0; // Loop through all the selected options
for ( ; i < max; i++ ) {//遍历
option = options[ i ]; // IE6-9 doesn't update selected after form reset (#2551)
if ( ( option.selected || i === index ) && //如果当前项是选中项
// Don't return options that are disabled or in a disabled optgroup
// 如果support.optDisabled为true,值为option.disabled取反
// 如果为假,值为option的属性disabled的值
// 如果值为null
( support.optDisabled ? !option.disabled : option.getAttribute( "disabled" ) === null ) &&
//且 如果select的disabled为假或者 optgroup的disabled为真
( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { // Get the specific value for the option
value = jQuery( option ).val(); // We don't need an array for one selects
if ( one ) {//单选直接返回
return value;
} // Multi-Selects return an array
values.push( value );//多选推入数组
}
} return values;//多选且没有没有默认项,不经过循环直接返回
}, set: function( elem, value ) {
var optionSet, option,
options = elem.options,
values = jQuery.makeArray( value ),//转为数组,value可以是任何值 "a"=>["a"]
i = options.length;//选项数量
//遍历
while ( i-- ) {
option = options[ i ];
//如果当前选项的值在values数组中,selected为true,否则为false
//可以用于设置多选的下拉单值
/*用法:
<select name="" id="" class="slt" multiple>
<option value="a">aaa</option>
<option value="b">bbbb</option>
<option value="c">ccccc</option>
</select>
<script>
$('.slt').val(["a","c"]);
</script>
*/
if ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) {
optionSet = true;//标识
}
} // force browsers to behave consistently when non-matching value is set
if ( !optionSet ) {
elem.selectedIndex = -1;
}
return values;
}
}
}
}); // Radios and checkboxes getter/setter
jQuery.each([ "radio", "checkbox" ], function() {
jQuery.valHooks[ this ] = {
set: function( elem, value ) {
if ( jQuery.isArray( value ) ) {
//如果传入的value是数组,判断当前元素的值是否在value数组中
//存在,则设置checked为true,并返回true,不存在则checked为false,并返回false
/*
用法:
<input type="checkbox" class="ck" value="a">
<input type="checkbox" class="ck" value="b">
<script>
$('.ck').val(["a","b"]);
</script>
*/
return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
}
}
};
if ( !support.checkOn ) {
jQuery.valHooks[ this ].get = function( elem ) {
//如果未指定value,返回on
//如果是 <input type="checkbox" class="ck" value>或者
//<input type="checkbox" class="ck" value="">这两种,返回的是""
return elem.getAttribute("value") === null ? "on" : elem.value;
};
}
});

可以看到,jQ的valHooks共有四个成员:

1、option

2、select

3、checkbox

4、radio

option中只有get方法,因为它的目的是在option中没有value值的时候去取中间的text值。

checkbox和radio中,set方法是考虑到同时为多个复选或者单选框设置值的情况,而get方法是考虑了没有初始化value时返回默认值“on”

select的set方法同复选单选框类似,而get方法中,如果是单选,直接返回value,如果是多选且有选中项,遍历后将结果推入数组最后返回数组,此外,它处理了option的disabled为true的情况,如果为true,获取不到值。这一点也是我的疑问,它为什么要这样做→ →

    <select name="" id="slt" class="slt">
<option value="a">aaa</option>
<option value="b">bbbb</option>
<option value="c" selected disabled>ccccc</option>
</select>
<script>
console.log($('#slt').val(),document.getElementById("slt").value);
</script>
// null "c"

jQuery val()方法及valHooks源码解读的更多相关文章

  1. jQuery.Callbacks 源码解读二

    一.参数标记 /* * once: 确保回调列表仅只fire一次 * unique: 在执行add操作中,确保回调列表中不存在重复的回调 * stopOnFalse: 当执行回调返回值为false,则 ...

  2. 第二十五课:jQuery.event.trigger的源码解读

    本课主要来讲解jQuery.event.trigger的源码解读. trigger = function(event, data, elem, onlyHandlers){ if(elem & ...

  3. 第二十四课:jQuery.event.remove,dispatch的源码解读

    本课还是来讲解一下jQuery是如何实现它的事件系统的.这一课我们先来讲一下jQuery.event.remove的源码解读. remove方法的目的是,根据用户传参,找到事件队列,从里面把匹配的ha ...

  4. 第二十三课:jQuery.event.add的原理以及源码解读

    本课主要来讲解一下jQuery是如何实现它的事件系统的. 我们先来看一个问题: 如果有一个表格有100个tr元素,每个都要绑定mouseover/mouseout事件,改成事件代理的方式,可以节省99 ...

  5. Go 源码解读|如何用好 errors 库的 errors.Is() 与 errors.As() 方法

    前言 快一个月没有更新技术文章了,这段时间投注了较多的时间学习字节的开源项目 Kitex/Hertz ,并维护一些简单的 issue ,有兴趣的同学也可以去了解: https://www.cloudw ...

  6. HttpServlet中service方法的源码解读

    前言     最近在看<Head First Servlet & JSP>这本书, 对servlet有了更加深入的理解.今天就来写一篇博客,谈一谈Servlet中一个重要的方法-- ...

  7. AbstractCollection类中的 T[] toArray(T[] a)方法源码解读

    一.源码解读 @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { //size为集合的大小 i ...

  8. SDWebImage源码解读之SDWebImageDownloaderOperation

    第七篇 前言 本篇文章主要讲解下载操作的相关知识,SDWebImageDownloaderOperation的主要任务是把一张图片从服务器下载到内存中.下载数据并不难,如何对下载这一系列的任务进行设计 ...

  9. String、StringBuffer、StringBuilder源码解读

    序 好长时间没有认真写博客了,过去的一年挺忙的.负责过数据库.线上运维环境.写代码.Code review等等东西挺多. 学习了不少多方面的东西,不过还是需要回归实际.加强内功,方能扛鼎. 去年学习M ...

随机推荐

  1. druid.io 海量实时OLAP数据仓库 (翻译+总结) (1)——分析框架如hive或者redshift(MPPDB)、ES等

    介绍 我是NDPmedia公司的大数据OLAP的资深高级工程师, 专注于OLAP领域, 现将一个成熟的可靠的高性能的海量实时OLAP数据仓库介绍给大家: druid.io NDPmedia在2014年 ...

  2. mysql 数据库电脑间迁移

    应用实例: database1(简称DB1)保存在PC1中的MySQL中,需要将DB1迁移到PC2中的MySQL中 环境: win7 MySQL5.7.13 参考: http://stackoverf ...

  3. python中的不可变类型和可变类型

    在python中整形,字符串,元组是不可变类型,而列表和字典都是可变类型. 对于不可变类型进行重新赋值,相当于是用以前的变量名重新指向了新的地址,这个地址中存的变量值就是重新的赋值 通过python中 ...

  4. [SDOI 2015] 星际战争

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=3993 [算法] 首先发现问题具有单调性 , 不妨二分答案mid 考虑网络流 : 将源 ...

  5. mysql函数之八:mysql函数大全

    对于针对字符串位置的操作,第一个位置被标记为1. ASCII(str) 返回字符串str的最左面字符的ASCII代码值.如果str是空字符串,返回0.如果str是NULL,返回NULL. mysql& ...

  6. 蓝桥杯 2014本科C++ B组 奇怪的分式 暴力枚举

    蓝桥杯 枚举 奇怪的分式 标题:奇怪的分式 上小学的时候,小明经常自己发明新算法.一次,老师出的题目是: 1/4 乘以 8/5 小明居然把分子拼接在一起,分母拼接在一起,答案是:18/45 (参见图1 ...

  7. SQL编程题-----1

    首先,题目给出这个数据库表格 要求写出SQL语句使之变成如下表格 解决方法: SELECT t1.Rq,t1.胜,t2.负 FROM         //t1和t2是自己命的新表格的名字 (SELEC ...

  8. 怎样通过计算机ip地址访问sql server 2008数据库

      在设置外网访问SQL2008数据库之前,首先必须保证局域网内访问SQL2008没有问题 .那么,我们先来看看局域网内访问SQL2008数据库需要哪些步骤和设置,才能做到在局域网内任何一台机器上输入 ...

  9. 解决在IE11浏览器上,css样式不起作用的问题

    1.首先下载http://pan.baidu.com/s/1c1DA1Ew并运行; 2.在列表中找到.css双击出现Edit File Type; 3.将MIME Type中改为text/css,点击 ...

  10. 可移植的配置visual studio工程第三方库

    现在编程有太多的好用的第三方库,例如 计算机视觉方面的opencv c++的扩充库boost 特殊的第三方库,相机库,通讯库等 使用这些库给我们带来了极大的便利,同时也有很多困扰.这个工程在我电脑上明 ...