【lodash源码】对toNumber的一些疑问

在拜读lodash时对作者的一些意图不太明白,前来请教。下面贴代码:

function toNumber (value) {
    if (typeof value == 'number') return value;
    if (isSymbol(value)) return NAN;
    if (isObject(value)) {
        var other = isFunction(value.valueOf) ? value.valueOf () : value;
        value = isObject(other) ? (other + '') : other;
    }
    if (typeof value != 'string') {
        return value === 0 ? value : +value;
    }
    value = value.replace (reTrim, '');
    var isBinary = reIsBinary.test (value);
    return (isBinary || reIsOctal.test (value))
        ? freeParseInt (value.slice (2), isBinary ? 2 : 8)
        : (reIsBadHex.test (value) ? NAN : +value);
}

下面是toNumber的一些实例:

    * _.toNumber(3.2);
    * // => 3.2
    *
    * _.toNumber(Number.MIN_VALUE);
    * // => 5e-324
    *
    * _.toNumber(Infinity);
    * // => Infinity
    *
    * _.toNumber('3.2');
    * // => 3.2

源码中有这么一段:

if (isObject(value)) {
        var other = isFunction(value.valueOf) ? value.valueOf () : value;
        value = isObject(other) ? (other + '') : other;
    }

先判断是不是object, 接着判断是不是function, 传入的参数是 value.valueOf。如果一开始传入的就是一个funciton, 那么other也将是一个function. 接下来对other进行isObject判断之后进行 + '' 操作。这样做有什么意义, 为什么不直接在得知是function之后返回 NAN ?

还有这一段:

var isBinary = reIsBinary.test (value);
return (isBinary || reIsOctal.test (value))
        ? freeParseInt (value.slice (2), isBinary ? 2 : 8)
        : (reIsBadHex.test (value) ? NAN : +value);

其中:

 /** Used to detect binary string values. */
//判断2进制
var reIsBinary = /^0b[01]+$/i;

/** Used to detect octal string values. */
//判断8进制
var reIsOctal = /^0o[0-7]+$/i;

 /** Used to detect bad signed hexadecimal string values. */
//判断16进制
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;

为什么在判断16进制时 是带有[-+]的?作者为什么对16进制的注释是 bad signed

阅读 4.4k
1 个回答

首先第一个问题:


if (isObject(value)) {
    var other = isFunction(value.valueOf) ? value.valueOf () : value;
    value = isObject(other) ? (other + '') : other;  
}

check isFunction的不是value本身, 而是value.valueOf, 需要了解Object.prototype.valueOf 这个built-in的方法, 默认对于Object而言是返回Object本身的, Function是继承了Object的, 而String, Number等都是有所定制的, 会反回对应的primitive值. 所以这里是check传入对象是否有valueOf这个方法(你可以给自己的定义的类型赋予不同的valueOf), 如果有的话, 用其返回的值(鼓励valueOf返回primitives).

然后根据返回值做第二次check并通过+ ""强制转换为primitive类型. 好处是什么?

主要是可以支持那些customized的类型, 比如:

const Switch = function(status) {
    this.status = status;
}
Switch.prototype.valueOf = function() {
    return this.status === "on" ? 1 : 0;
}
let s = new Switch("on");
toNumber(s);
// 1

至于后面的16进制的正则, 主要是因为-|+在js中都可以作为unary operator, 也就是sign, 所以0xf => +0xf => 15, -0xf => -15, bad的含义在于这不是正常的正负数的16进制表示法...

推荐问题
宣传栏