关于面试题 Array.indexof() 方法的实现及思考

这是我在面试大公司时碰到的一个笔试题,当时自己云里雾里的胡写了一番,回头也曾思考过,最终没实现也就不了了之了。

昨天看到有网友说面试中也碰到过这个问题,我就重新思考了这个问题的实现方法。

对于想进大公司的童鞋,我想多说两句,基础知识真的很关键。平时在工作中也深刻体会到,没有扎实的基础知识,简单问题容易复杂化。

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

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

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

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

最终代码如下

关于面试题 Array.indexof() 方法的实现及思考关于面试题 Array.indexof() 方法的实现及思考

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++) {
            // 如果相等则返回当前索引值
            else if (searchElement === this[i]) {
                return i;
            }
        }

        return -1
}
View Code

测试数组

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

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

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

关于面试题 Array.indexof() 方法的实现及思考关于面试题 Array.indexof() 方法的实现及思考

// 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;
  };
}
View Code

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

相关推荐