轻剑的招式练完了,剑鞘里还藏着几件小工具——不用选元素,直接对数组、对象、表单下手。 它们不起眼,却能把一串啰嗦的循环缩成一行。

本式要点
  • 数组三件套:$.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),值在前。只用一个参数时拿到的都是元素本身, 要同时用两个参数时才见分晓。

例 1 · 一条数据流水线:筛选 → 变换 → 渲染

成绩单:

    注意“全部翻倍”只是渲染翻倍后的新数组,原始数据没被动过—— $.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())
    例 2 · 小工具速验:点一下看一行结果
    点上面的按钮,结果显示在这里。

    桩:A · B · C

    合并配置:$.extend

    $.extend(target, source) 把 source 的属性复制进 target,常用于 “默认配置 + 用户配置”合并:用户给了就覆盖,没给就用默认值。 传 true 作为第一个参数是深合并——嵌套对象也逐层合并, 而不是整块覆盖。写插件、写组件时,这是最常见的一招。

    例 3 · 浅合并与深合并的区别
    默认配置:{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 提交数据、拼查询参数时,它替你省去手写的麻烦。

    例 4 · 把小表单变成查询串
    点「生成查询串」试试。

    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。教程从第五式起就只教新写法,正是这个原因: 不是它们坏了,而是新写法更好、更统一。

    练功 · 第十一式
    1. 用 $.grep 与 $.map 一行连写:先从 [1, 2, 3, 4, 5, 6] 中挑出偶数,再把每个数平方。
    2. 用 $.extend(true, …) 合并两份嵌套配置:默认 {ui:{theme:'light', font:14}},用户 {ui:{font:16}},预期结果是主题与字号都在。
    3. 思考题:为什么 $.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() 等只是贬值——查源码,别信道听途说。
    下一式,我们把链式调用拆开看,并顺手学会量尺寸、定位置。