likes
comments
collection

JavaScript奇怪行为大赏

作者站长头像
站长
· 阅读数 8

JavaScript是一种脚本语言,是前端语言的基础,无论是学习哪种前端框架,学好JS都是很有必要的。JavaScript是Brendan Eich在1995年发明的语言,为网景浏览器Netscape 2发明,在1997年成为ECMA-262标准的一部分。

JavaScript奇怪行为大赏
JavaScript之父-Brendan Eich

JS的设计初衷只是为了完成简单的网页互动,并没有考虑复杂应用的需要,设计者只用了10天的时间完成了设计,另外由于设计本身擅长函数式编程,但是又需要将JS往面向对象上靠拢,出于设计简单脚本语言的想法放弃了「类」的想法,采用prototype继承模型,使这门语言「四不像」。由于JS语言一经推出就立刻受到广泛接受,用户呈爆炸式增长,使其没有时间调整设计,缺乏积累过程,同时由于网景和微软的JScript竞争,强势申请JS的国际标准,使得JS在推出一年半之后就称为标准。

JS设计之初并未想到会成为一门爆炸式的流行语言,以及以上原因,因此在语法设计上存在很多「语法缺陷」,但这同时也是JS的强大之处。

文章结合JS语法以及使用经验,对JS中数字的处理问题进行列举和说明,用于在实际编程中避免踩坑,如有问题,欢迎指正。

parseInt

原理

perseInt(value, radix),将指定为radix进制的value转为10进制整数

机制:parseInt会逐字符解析,直到遇到无法解析的字符

例子

比如:

parseInt('f*ck', 16) // 15
parseInt('1cdfed013*ck', 16) // 7750995987

将 "Infinity" 转为不同进制的数字:

//
parseInt("Infinity", 10); // -> NaN
// ...
parseInt("Infinity", 18); // -> NaN...
parseInt("Infinity", 19); // -> 18
// ...
parseInt("Infinity", 23); // -> 18...
parseInt("Infinity", 24); // -> 151176378
// ...
parseInt("Infinity", 29); // -> 385849803
parseInt("Infinity", 30); // -> 13693557269
// ...
parseInt("Infinity", 34); // -> 28872273981
parseInt("Infinity", 35); // -> 1201203301724
parseInt("Infinity", 36); // -> 1461559270678...
parseInt("Infinity", 37); // -> NaN

警惕空值

在使用parseInt进行数字转换时,要注意null空值判断

parseInt(null, 24) // 23

==, >, >=的比较规则

null == 0; // false
null > 0; // false
null >=0; // true

== 进行比较时,如果有非数字,会进行数字转换;但是如果有一侧是null/undefined,那么另一侧也必须是其中一个才会进行转换,否则不转;

对两侧进行数字转换,+null -> 0

= 并不等同于大于或等于,而是对小于比较的结果取反,null >= 0等同于 null < 0,+null < 0, 0 < 0,返回false,取反返回true

连续比较

1 < 2 < 3; // -> true
3 > 2 > 1; // -> false

按照从左到右的顺序执行,

1 < 2 < 3 // 1 < 2 -> true
true < 3 // true -> 1
1 < 3 // true
3 > 2 > 1 // 3 > 2 -> true
true > 1 // true -> 1
1 > 1 // false

❓0.1 + 0.2 === 0.3

0.1 + 0.2 === 0.3 // false

程序中的常数0.2和0.3也是它们的真实值的近似值。与0.2最接近的双精度数大于有理数0.2,而与0.3最接近的双精度数小于有理数0.3。0.1和0.2的和最终比有理数0.3大,因此与代码中的常数不一致。

详细解释参见 0.30000000000000004.com

不只有JS中会有这个问题,使用浮点数学的语言都会有。

JS中中最小值大于0

Number.MIN_VALUE > 0; // -> true

Number.MIN_VALUE 是5e-324,是浮点数精度能标识的最小正数,也是最接近0的数字;

正数范围内的最小值是Number.NEGATIVE_INFINITY,尽管严格意义上讲这并不是一个数字。

双小数点

27.toString() // Uncaught SyntaxError: Invalid or unexpected token

使用双小数点可以解决问题:

27..toString() // '27'

原因:以上现象只是JS的语法限制。.有语法歧义,既可以作为成员操作符,又可以是数值后的小数点,取决于使用场景。

标准上关于例子中点位置的解释是数值后的小数点,这是由ECMAScript的数值型语法定义的,因此必须使用两个点,或者添加括号的方式才能使上述语法生效。

(27).toString() // '27'
// 或者
27..toString(); // '27'

return

(function() {
  return
  {
    b: 10;
  }
})(); // -> undefined
let f = () => {};
f(); // -> undefined
// {}被作为函数的一部分,因此返回undefined
let f = () => ({});
f(); // -> {}

比如在使用map函数映射对象时,省略return的方式:

const mockData = [{name: 'lily'}, {name: 'mike'}];
const result = mockData.map(item => ({name: item.name, key: item.name}));
const result = mockData.map(item => ({name: item.name, key: item.name}));

总结

文章罗列了JS在处理数值时的一些易出错或不常见的问题,在处理数值逻辑的时候需要注意,避免踩坑。

如果你遇到过JS中其他奇怪行为,欢迎评论区评论交流,一起进步吖❤️❤️❤️