博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
怪异的JavaScript系列(三)
阅读量:6944 次
发布时间:2019-06-27

本文共 3212 字,大约阅读时间需要 10 分钟。

译者按: JavaScript有很多坑,经常一不小心就要写bug。

  • 原文:
  • 译者:

为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。

JavaScript是一门伟大的语言,它拥有非常简洁的语法,庞大的生态系统,以及最重要的:有一个伟大的社区支撑着。同时,我们也知道JavaScript是一个充满技巧性的语言。有些坑足以让我们崩溃,也有些奇淫技巧让我们觉得很有趣。本文的思想源自于在dotJS2012上的演讲。

我收集这些例子的主要目的是将它们整理并清楚理解它们的原理。从中学到很多以前不懂的知识是一件很有趣的事情。如果你是初学者,你可以通过学习这些笔记深入理解JavaScript;如果你是一个专业的开发者,那么可以将这些笔记作为一个不错的引用资料。不管怎样,只要读下去,你就会学到新东西的。

return

下面的函数返回的结果竟然不是对象{b:10}

(function () {  return  {    b : 10  }})() // -> undefined复制代码

不过,如果稍微改写一下,就不一样了:

(function () {  return {    b : 10  }})() // -> { b: 10 }复制代码

这主要是因为有一个自动行尾加分号的机制在作怪,会自动在很多新行的行尾添加分号。在第一个例子中,实际上是在return后面添加了分号。

(function () {  return ;  {    b : 10  }})() // -> undefined复制代码

JavaScript坑很多,赶紧使用扶一扶!

0.1+0.2=?

一个众所周知的笑话就是0.1加上0.2竟然不等于0.3。

0.1 + 0.2 // -> 0.30000000000000004(0.1 + 0.2) === 0.3 // -> false复制代码

在StackOverflow上有关提到这样的问题“”:

你的程序中0.2和0.3会在底层用相近的数据表达。double类型数据中离0.2最近的数要比0.2大一点点。离0.3最近的double类型数据又刚好比0.3小一点点。所以,结果就是0.1+0.2的结果比0.3大。

这个问题非常出名,以至于有一个专门的网站。在所有使用浮点计算的语言中都有这个问题,不止JavaScript。

神奇的加法操作

999999999999999  // -> 9999999999999999999999999999999 // -> 1000000000000000010000000000000000       // -> 1000000000000000010000000000000000 + 1   // -> 1000000000000000010000000000000000 + 1.1 // -> 10000000000000002复制代码

这个是依据IEEE 754-2008标准确定的二进制浮点运算。当数值大到这个程度,它会取整到最近的偶数。参考:

为Number自定义

你可以为NumberString添加自定义函数:

Number.prototype.isOne = function () {  return Number(this) === 1}1.0.isOne() // -> true1..isOne()  // -> true2.0.isOne() // -> false(7).isOne() // -> false复制代码

你可以想操纵其它对象一样去扩展Number对象。不过,如果定义的函数不在它本身的定义规范(Specification)中,那么不建议这么做。这里是一个参考列表:

3个number比较

1 < 2 < 3 // -> true3 > 2 > 1 // -> false复制代码

我们来看看具体的执行过程就明白了:

1 < 2 < 3 // 1 < 2 -> truetrue  < 3 // true -> 11     < 3 // -> true3 > 2 > 1 // 3 > 2 -> truetrue  > 1 // true -> 11     > 1 // -> false复制代码

有趣的数学

3  - 1  // -> 2 3  + 1  // -> 4'3' - 1  // -> 2'3' + 1  // -> '31''' + '' // -> ''[] + [] // -> ''{} + [] // -> 0[] + {} // -> '[object Object]'{} + {} // -> '[object Object][object Object]''222' - -'111' // -> 333[4] * [4]       // -> 16[] * []         // -> 0[4, 4] * [4, 4] // NaN复制代码

到底是为什么呢? 下面有一个表供快速参考:

Number  + Number  -> additionBoolean + Number  -> additionBoolean + Boolean -> additionNumber  + String  -> concatenationString  + Boolean -> concatenationString  + String  -> concatenation复制代码

那么其他例子呢?对于[]{},toPrimitive和toString方法会在加法操作前被隐式地调用。

正则也可以做加法?

// Patch a toString methodRegExp.prototype.toString = function() {  return this.source}/7/ - /5/ // -> 2复制代码

参考:

箭头函数

let f = () => 10f() // -> 10复制代码

好的,但是下面这个呢:

let f = () => {}f() // -> undefined复制代码

你也许期待着返回{},而不是undefined。着主要是因为大括号也是函数定义语法的一部分。如果你真想返回大括号,可以这么写:

let f = () => ({})f() // -> {}复制代码

Math.max()比Math.min()小

Math.min(1,4,7,2)  // -> 1Math.max(1,4,7,2) // -> 7Math.min() // -> InfinityMath.max() // -> -InfinityMath.min() > Math.max() // -> true复制代码

原因:

String不是String的实例

'str' // -> 'str'typeof 'str' // -> 'string''str' instanceof String // -> false复制代码

构造函数String返回一个字符串:

typeof String('str')   // -> 'string'String('str')          // -> 'str'String('str') == 'str' // -> true复制代码

如果我们用new来构建的话:

new String('str') == 'str' // -> truetypeof new String('str')   // -> 'object'复制代码

竟然变成了一个对象!

new String('str') // -> [String: 'str']复制代码

参考:

往期参考

转载地址:http://slanl.baihongyu.com/

你可能感兴趣的文章
vc++加载透明png图片方法-GDI+和CImage两种
查看>>
十五天精通WCF——第十二天 说说wcf中的那几种序列化
查看>>
每天一个linux命令(10):cat 命令
查看>>
android ScrollView中嵌套listview listview可点击处理,可展开
查看>>
一个由proguard与fastJson引起的血案(转)
查看>>
clearing & settlement
查看>>
Lingo 做线性规划 - DEA
查看>>
Axure 全局辅助线(转)
查看>>
js原生设计模式——9外观模式封装2(小型代码库YJ)
查看>>
onvif开发实战2--总结框架搭建
查看>>
Apache ab测试工具使用方法(无参、get传参、post传参)
查看>>
单例设计模式之安全的懒汉式
查看>>
iOS_20_微博OAuth授权_取得用户授权的accessToken
查看>>
离线用户的灰色头像处理
查看>>
php递归函数return会出现无法正确返回想要值的情况
查看>>
Android Studio之Activity切换动画(三)
查看>>
Bitcoin: A Peer-to-Peer Electronic Cash System(比特币论文翻译)
查看>>
Redis-Redi事务注意事项
查看>>
ffmpeg mediacodec 硬解初探
查看>>
Cocostudio 1.4 实现的DemoShop
查看>>