轻剑的招式练完了,剑鞘里还藏着几件小工具——不用选元素,直接对数组、对象、表单下手。 它们不起眼,却能把一串啰嗦的循环缩成一行。
- 数组三件套:
$.each遍历、$.map变换、$.grep筛选 - 查找与合并:
$.inArray、$.merge、$.makeArray、$.uniqueSort $.extend合并对象(浅合并与深合并),$.isEmptyObject/$.isPlainObject判断$.param把对象或表单数据变成查询串- 认清 jQuery 4.0 的删与留:哪些没了、哪些还在(附实测结论)
数组三件套:each / map / grep
三个方法分工明确:$.each(arr, fn) 逐个走一遍(只管“看”);
$.map(arr, fn) 把每个元素变换成新值,返回新数组;
$.grep(arr, fn) 按条件筛选,返回通过考验的那些元素。
回调的参数顺序分两派,别记混:$.each(和 $(...).each() 一样)是
function (index, value),下标在前;$.map 与 $.grep 则是
function (value, index),值在前。只用一个参数时拿到的都是元素本身,
要同时用两个参数时才见分晓。
成绩单:
注意“全部翻倍”只是渲染翻倍后的新数组,原始数据没被动过——
$.map 返回新数组,这正是函数式写法的好处:进来的数据永远安全。
查找、合并与转换
剩下几个小工具,各自解决一个具体问题:
| 方法 | 用途 | 例子 |
|---|---|---|
$.inArray(v, arr) | 找值在数组中的下标,找不到返回 -1 | $.inArray('剑', bag) |
$.merge(a, b) | 把 b 并进 a(改动 a 并返回它,不是新数组) | $.merge([1,2],[3]) |
$.makeArray(obj) | 把类数组(DOM 集合、arguments)转成真数组 | $.makeArray(document.querySelectorAll('li')) |
$.uniqueSort(arr) | 给 DOM 元素数组去重并按文档顺序排序;普通数字、字符串数组会原样返回,不会“去重排序” | $.uniqueSort($('li').toArray()) |
点上面的按钮,结果显示在这里。
桩:A · B · C
合并配置:$.extend
$.extend(target, source) 把 source 的属性复制进 target,常用于
“默认配置 + 用户配置”合并:用户给了就覆盖,没给就用默认值。
传 true 作为第一个参数是深合并——嵌套对象也逐层合并,
而不是整块覆盖。写插件、写组件时,这是最常见的一招。
默认配置:{theme:"light", page:{size:10, sort:"asc"}}
用户配置:{page:{size:20}}
顺带记两个判断函数:$.isEmptyObject(obj) 判空对象、
$.isPlainObject(obj) 判“是不是纯对象”(由 {} 或
new Object() 创建)。它们常与 $.extend 结伴出现。
表单转查询串:$.param
$.param(obj) 把对象变成 key=value&key=value 形式的查询串,
中文与特殊字符会自动做 URL 编码。Ajax 用 GET 提交数据、拼查询参数时,它替你省去手写的麻烦。
点「生成查询串」试试。
jQuery 4.0 的删与留
工具函数这一带,是版本变迁的重灾区。网上不少老文章还在教的写法,在 jQuery 4.0.0 里已经不复存在——调用即报错。下表以本站携带的 jQuery 4.0.0 源码为准,全部核实过:
| 已经移除(调用即报错) | 替代写法 |
|---|---|
$.trim(s) | s.trim()(原生字符串方法) |
$.type(x) / $.isArray(x) / $.isFunction(x) | typeof / Array.isArray() / typeof x === 'function' |
$.isNumeric(x) / $.isWindow(x) | typeof x === 'number' / x != null && x === x.window |
$.parseJSON(s) | JSON.parse(s) |
$.now() | Date.now() |
$.nodeName() / $.camelCase() | 原生属性判断 / 自行处理字符串 |
.live() / .die() | on() / off()(1.7 起弃用、1.9 起移除) |
.bind() / .unbind() / .delegate() /
.undelegate() 与 $.proxy() 在 4.0.0 里仍然存在,也仍然能跑——
它们已经被“贬值”(deprecated),官方建议改用 on() / off() 与原生
Function#bind。教程从第五式起就只教新写法,正是这个原因:
不是它们坏了,而是新写法更好、更统一。
- 用
$.grep与$.map一行连写:先从[1, 2, 3, 4, 5, 6]中挑出偶数,再把每个数平方。 - 用
$.extend(true, …)合并两份嵌套配置:默认{ui:{theme:'light', font:14}},用户{ui:{font:16}},预期结果是主题与字号都在。 - 思考题:为什么
$.trim被移除了,而.bind()却还留着?
参考答案 1
$.grep 先筛出 [2, 4, 6],$.map 再变换成
[4, 16, 36]。两个方法都返回新数组,可以放心链式连写。
参考答案 2
第一个参数 true 是深合并开关,第二个 {} 是空目标对象——
从空对象起手,默认配置对象就不会被改写,这一点在写插件时尤其重要。
参考答案 3
因为它们的“替代品”位置不同。$.trim 的功能早已被
String.prototype.trim() 原生实现,浏览器普遍自带,jQuery 没有理由再背一份;
而 .bind() 这类方法的替代品 on() 仍是 jQuery 自己的 API,
老代码里用量巨大,一口气砍掉会伤及太多项目,所以官方选择
“保留但贬值”:能跑、不推荐、未来某个大版本再谈移除。写新代码时,直接照新写法来就好。
本式小结
$.each遍历(返回原集合)、$.map/$.grep变换与筛选(返回新数组);$.inArray找不到返回-1;$.merge是原地改动,别拿它当“复制”;$.extend合并配置,嵌套结构记得加true深合并并传入空对象当目标;$.param生成查询串,配合 Ajax 的 GET 请求刚好;- 版本事实要认准:
$.trim等已移除,.bind()等只是贬值——查源码,别信道听途说。
下一式,我们把链式调用拆开看,并顺手学会量尺寸、定位置。