介绍
jq 有一个 each 方法,是一个通用遍历方法。可用于遍历对象和数组。
语法
jQuery.each(object, [callback]);
callback 有两个参数:第一个是对象的属性名或者是数组的索引,第二个为对应的值。
// 数组$.each( [0,1,2], function(i, n){console.log( "Item #" + i + ": " + n );});// Item #0: 0// Item #1: 1// Item #2: 2// 对象$.each({ name: "John", lang: "JS" }, function(i, n) {console.log("Name: " + i + ", Value: " + n);});// "Name: name, Value: John"// "Name: lang, Value: JS"
ES5 提供的 forEach 方法不能跳出循环,但 jq 的 each 方法可以。
$.each( [0, 1, 2, 3, 4, 5], function(i, n){if (i > 2) return false;console.log( "Item #" + i + ": " + n );});// Item #0: 0// Item #1: 1// Item #2: 2
实现 each
根据参数类型的不同选择不用的循环语句,数组就调用 for 循环,对象就调用 for in 循环。对于类数组对象也选择 for 循环。
可以利用在 《javascript 类型判断(plainObject …》中讲到的 isArrayLike 方法。
function each(obj, callback) {let length, i = 0;// 类数组对象就使用 for 循环if (isArrayLike(obj)) {length = obj.length;for (; i < length; i++) {callback(i, obj[i]);}} else {// 对象使用 for in 循环for (i in obj) {if (obj.hasOwnProperty(i)) {callback(i, obj[i]);}}}return obj;}
支持终止循环
把
callback(i, obj[i])
替换成
if (callback(i, obj[i]) === false) break;
支持 this,能够指向当前遍历的元素。
例子
// 我们给每个人添加一个 age 属性,age 的值为 18 + indexvar person = [{name: 'kevin'},{name: 'daisy'}]$.each(person, function(index, item){this.age = 18 + index;})
把
if (callback(i, obj[i]) === false) break;
替换为
if(callback.call(obj[i], i, obj[i]) === false) break;
最终代码
function each(obj, callback) {let length, i = 0;// 类数组对象就使用 for 循环if (isArrayLike(obj)) {length = obj.length;for (; i < length; i++) {if(callback.call(obj[i], i, obj[i]) === false) break;}} else {// 对象使用 for in 循环for (i in obj) {if (obj.hasOwnProperty(i)) {if(callback.call(obj[i], i, obj[i]) === false) break;}}}return obj;}
性能比较
const arr = Array.from({length: 1000000}, (v, i) => i);console.time("for");let i = 0, valueOne = 0;for (; i < arr.length; i++) {valueOne += arr[i];}console.timeEnd("for");console.time("each");let valueTwo = 0;each(arr, function (index, item) {valueTwo += item;});console.timeEnd("each");
结果

我们都知道 each 也是使用 for 循环,但为什么时间会差这么多了?它们的唯一区别是有没有使用 call 方法,可见 call 方法是造成性能损失的原因。
参考:
[1] JavaScript专题之jQuery通用遍历方法each的实现
[2] forEach
[3] for in
