做题之['1', '2', '3'].map(parseInt)

389 阅读3分钟

前言

题目:['1', '2', '3'].map(parseInt) what & why ?

题目来源:juejin.cn/post/684490…

运行结果

[1, NaN, NaN]

解题思路

  • 从map函数的内部实现开始探究
  • parseInt函数的传参探究

map方法的内部实现

  • 源码
if (!Array.prototype.map) {
  Array.prototype.map = function(callback, thisArg) {
    var T, A, k;
    if (this == null) {
      throw new TypeError(" this is null or not defined");
    }
    // 1. 将O赋值为调用map方法的数组.
    var O = Object(this);
    // 2.将len赋值为数组O的长度.
    var len = O.length >>> 0;
    // 3.如果callback不是函数,则抛出TypeError异常.
    if (Object.prototype.toString.call(callback) != "[object Function]") {
      throw new TypeError(callback + " is not a function");
    }
    // 4. 如果参数thisArg有值,则将T赋值为thisArg;否则T为undefined.
    if (thisArg) {
      T = thisArg;
    }
    // 5. 创建新数组A,长度为原数组O长度len
    A = new Array(len);
    // 6. 将k赋值为0
    k = 0;
    // 7. 当 k < len 时,执行循环.
    while(k < len) {
      var kValue, mappedValue;
      //遍历O,k为原数组索引
      if (k in O) {
        //kValue为索引k对应的值.
        kValue = O[ k ];
        // 执行callback,this指向T,参数有三个.分别是kValue:值,k:索引,O:原数组.
        mappedValue = callback.call(T, kValue, k, O);
        // 返回值添加到新数组A中.
        A[ k ] = mappedValue;
      }
      // k自增1
      k++;
    }
    // 8. 返回新数组A
    return A;
  };
}

这个过程主要分为以下几步:

1、判断this是否存在,也就是作用的数组存不存在
2、判断数组的长度,并且获取数组长度
3、检测callback是否是函数
4、生成一个长度相等的空数组
5、循环调用数组中的每个元素,将每个元素传入callback,并且获取到返回值
6、返回新生成的数组

那么问题来了,会是哪一步出现问题了呢

mappedValue = callback.call(T, kValue, k, O);

仔细阅读源码,发现其他步骤都不会出现问题,只是生成的值出现了偏差,那么我们将怀疑的眼光放到这一步上,我们会发现,循环执行的步骤如下:

parseInt.call(undefined, '1', 0, ['1', '2', '3']);
parseInt.call(undefined, '2', 1, ['1', '2', '3']);
parseInt.call(undefined, '3', 2, ['1', '2', '3']);

返回的结果是:

1
NaN
NaN

刚好是我们得到的结果。那么会什么会产生NaN呢,让我们一起探索一下parseInt的接收参数。

parseInt方法详解

parseInt的MDN地址

  • 接收的参数

string:接收的参数。 radix:进制。比如我们常说的二进制,十进制等。

  • 返回值

如果无法解析,返回NaN。

结果分析

parseInt.call(undefined, '1', 0, ['1', '2', '3']);
parseInt.call(undefined, '2', 1, ['1', '2', '3']);
parseInt.call(undefined, '3', 2, ['1', '2', '3']);

这是执行的代码,我们改的简单一点,如下所示:

parseInt('1', 0);
parseInt('2', 1);
parseInt('3', 2);

我们逐个分析:

parseInt('1', 0);

0就相当于十进制,所以,直接返回的结果是1。

parseInt('2', 1);

1代表的是一进制,并不存在,因为一进制无法表示任何东西,所以返回NaN。

parseInt('3', 2);

2代表的是二进制,而二进制中,只能出现1和0两个数字,比如上述代码中的3,根本无法转化成相对应的整数,所以返回NaN。

总结

通过这道题目,我清楚的了解了两个东西:

  • map是如何实现的(原理)
  • parseInt的第二个参数的用法