• JavaScript之map与parseInt的陷阱


    问题来源

    ​ 这个问题的来源是学习廖雪峰老师JS教程。问题如下:小明希望利用map()把字符串变成整数,他写的代码很简洁:

    'use strict';
    
    var arr = ['1', '2', '3'];
    var r;
    r = arr.map(parseInt);
    console.log(r);
    // [1, NaN, NaN]
    

    为什么不是[1, 2, 3]?这是因为两个两个函数的定义有冲突。下面详解:

    map的定义

    ​ 注意到这个问题的原因是参考了这个国外某博客JavaScript可选参数危险。首先,我们了解一下map方法的定义,如下:

    var new_array = arr.map(function callback(currentValue[, index[, array]]) {
        // Return element for new_array
    }[, thisArg])
    

    其中参数有一个函数callback,这个函数需要三个参数:currentValue(必须):处理的数组中的当前元素;index(可选):当前处理的元素在数组中的索引值;array(可选):调用map的数组。thisArg(可选):对象作为该执行回调时使用,传递给函数,用作 "this" 的值。
    如果省略了 thisValue ,"this" 的值为 "undefined"。

    ​ 所以,map函数接收的是两个参数,一个函数,另一个是thisArg。这里我们主要关注的是其中的函数接收三个参数,一个必须,两个可选。问题就是出现在这里,函数接收三个参数。

    parseInt的定义

    ​ 这个函数用于解析一个字符串,并返回一个整数。定义如下:

    parseInt(string, radix)
    

    参数string(必须):表示的是要被解析的字符串。radix(可选):表示表示要解析的数字的基数。该值介于 2 ~ 36 之间。如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x” 或 “0X” 开头,将以 16 为基数。如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。第二个可选参数,就是问题的另一来源了。

    问题详解

    ​ 了解完两个函数的定义后,我们就知道小明代码的问题了:

    var arr = ['1', '2', '3'];
    var r;
    r = arr.map(parseInt);
    

    我们通常以为上述代码中 arr.map(parseInt);表示的是

    parseInt("1")
    parseInt("2")
    parseInt("3")
    

    实际上应该是:

    parseInt("1", 0, arr)
    parseInt("2", 1, arr)
    parseInt("3", 2, arr)
    

    其中的arr['1', '2', '3']。我们知道,JavaScript函数通常会忽略额外的参数,并且parseInt只需要两个参数,因此我们不必担心theArray这些调用中参数的影响。但是,第二个参数对parseInt影响很大。parseInt("1", 0)没有问题,0表示的是以二进制为基数解析‘1’。但是后面的parseInt("2", 1)以及parseInt("3", 2)就有问题了。1parseInt中是无效的基数,返回‘NaN’值;2虽然是有意义的基数,但是因为‘3’不是合法的二进制数,所以也返回的是NaN。至此,问题错误已经明了。下面是解决方案。

    解决方案

    ​ 解决的方法很简单,就是修饰一些parseInt函数。代码如下:

    'use strict';
    
    var arr = ['1', '2', '3'];
    var r;
    r = arr.map(function parseInt2(x) {
        return parseInt(x);
    });
    console.log(r);
    

    或者我们使用Number()方法,这样也会把字符串参数解析成十进制数,并且只需要一个参数。代码如下:

    'use strict';
    
    var arr = ['1', '2', '3'];
    var r;
    r = arr.map(Number);
    console.log(r);
    

    当然,也可以从map下手解决问题。一个可能的方法如下:

    Function.prototype.only = function(numberOfArgs) {
       var self = this; 	//the original function
       return function() {
          return self.apply(this,[].slice.call(arguments,0,numberOfArgs))
       }
    };
    arr.map(parseInt.only(1));
    

    以上,就是JavaScript中map与parseInt冲突的问题的来源、解析、解决了。

  • 相关阅读:
    iOS酷炫动画效果合集
    重载hash与isEqual:方法
    NSObject的hash方法
    带辉光效果的跑马灯
    线性重复动画
    TextKit简单示例
    计算一行文本的高度
    点击cell动态修改高度动画
    FastDFS图片服务器(分布式文件系统)学习。
    Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'jdbc.username' in string value "${jdbc.username}"
  • 原文地址:https://www.cnblogs.com/cjvae/p/9782387.html
Copyright © 2020-2023  润新知