Array.prototype.indexof的实现原理

因为存在 indexOf 的方法,所以自定义方法写成 indexof ,方便对比。

对于 Array.indexof() 方法的实现,主要考察的就是原型继承的知识。

通过 Array.prototype.indexof = function(){} 就可以给 Array 添加一个方法,实际工作中不推荐这样做。

剩下的就是数组元素匹配的问题,就不多说了,虽然不难,但是做的过程中也遇到了不大不小的问题。

最终代码如下

Array.prototype.indexof = function(searchElement, fromIndex) {

var len = this.length;

// 首先判断 fromIndex 是否合法
if (fromIndex == null) {
fromIndex = 0;
}
if (fromIndex < 0) {
fromIndex = len - 1;
}

// 循环判断 searchElement 是否与数组内元素相等
for (var i = fromIndex; i < len; i++) {
// 如果相等则返回当前索引值
if (searchElement === this[i]) {
return i;
}
}

return -1
}

测试数组

 
  1. var arr = ['a', '0', 0, 'a'];

试了试,基本和原生方法差不多,没有太明显的bug,但是总觉得自己的代码有些不够简练,逻辑不够严谨。如果文章到此就结束了,显的有点水。

翻 MDN 的时候看到了一个关于 Array.indexOf() 方法的 polyfill,因为该方法是 ECMAScript 第五版中实现的,所以没有原生支持的时候就会用如下方法实现。也就是这个问题有了一个官方答案。我认为大家可以先不看官方代码,自己尝试着写一写,然后再对比答案就会发现自己的不足。

// Production steps of ECMA-262, Edition 5, 15.4.4.14
// Reference: http://es5.github.io/#x15.4.4.14
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function(searchElement, fromIndex) {

var k;

// 1. Let o be the result of calling ToObject passing
// the this value as the argument.
if (this == null) {
throw new TypeError('"this" is null or not defined');
}

var o = Object(this);

// 2. Let lenValue be the result of calling the Get
// internal method of o with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = o.length >>> 0;

// 4. If len is 0, return -1.
if (len === 0) {
return -1;
}

// 5. If argument fromIndex was passed let n be
// ToInteger(fromIndex); else let n be 0.
var n = +fromIndex || 0;

if (Math.abs(n) === Infinity) {
n = 0;
}

// 6. If n >= len, return -1.
if (n >= len) {
return -1;
}

// 7. If n >= 0, then Let k be n.
// 8. Else, n<0, Let k be len - abs(n).
// If k is less than 0, then let k be 0.
k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);

// 9. Repeat, while k < len
while (k < len) {
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the
// HasProperty internal method of o with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
// i. Let elementK be the result of calling the Get
// internal method of o with the argument ToString(k).
// ii. Let same be the result of applying the
// Strict Equality Comparison Algorithm to
// searchElement and elementK.
// iii. If same is true, return k.
if (k in o && o[k] === searchElement) {
return k;
}
k++;
}
return -1;
};
}

仔细看了看官方代码,思路清晰,逻辑严谨,代码简洁,再回头看看自己的代码,真是惨不忍睹,实在很惭愧。这个问题不难,但是通过阅读官方代码,发现这其中有很多值得学习的地方,尤其是条件判断是否全面,考虑问题是否周到。我从不敢以程序员自诩,至少现在看来自己还不够格。解决一个问题很简单,但是能不能把问题解决好就是能力的体现。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用以下代码来优化上述代码,实现通过点击表格的日期表头来升序或降序排列表格行: ```javascript var table = document.getElementById("showTable"); var dateHeader = table.querySelector("#dateHeader"); var rows = Array.from(table.tBodies[0].rows); // 将日期字符串转换为Date对象并将其存储在数组中 var dates = rows.map(function(row) { var dateStr = row.cells[2].textContent; var dateParts = dateStr.split("-"); return new Date(dateParts[0], dateParts[1] - 1, dateParts[2]); }); // 添加事件监听器以在单击表头时对表格进行排序 dateHeader.addEventListener("click", function () { // 判断当前排序顺序并按相反的顺序对行进行排序 if (dateHeader.getAttribute("data-order") === "desc") { rows.sort(function (a, b) { return dates[rows.indexOf(a)] - dates[rows.indexOf(b)]; }); dateHeader.setAttribute("data-order", "asc"); } else { rows.sort(function (a, b) { return dates[rows.indexOf(b)] - dates[rows.indexOf(a)]; }); dateHeader.setAttribute("data-order", "desc"); } // 使用排序后的行更新表格 rows.forEach(function(row) { table.tBodies[0].appendChild(row); }); }); ``` 这段代码的优化点包括: - 使用 `Array.from()` 方法将表格的行转换为数组,而不是使用 `for` 循环遍历。 - 使用 `map()` 方法将日期字符串转换为日期对象,并将结果存储在数组中。 - 在排序函数中直接使用 `rows.indexOf()` 方法获取行的索引,而不是使用循环变量 `i`。 - 使用 `forEach()` 方法将排序后的行添加回表格中,而不是使用 `for` 循环遍历。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值