当下JavaScript越来越流行,成为长期霸语言榜前三的语言。但是实际上JavaScript是一个很丑陋有很多槽点的语言,这就是为什么新出了那么多框架(从jQuery到Vue)以及海尔斯伯格大大推出新流行语言的Type Script的直接原因,避免大家去直接用JavaScript写代码。虽然这几年随着ECMAScript 6(ES6)推出,JavaScript逐渐变得好用起来,但是JavaScript确实一直存在这一些挥之不去的痛。
本文虫虫就来和大家一起细数下JavaScript的一些语言痛点,知短而成长也是成功法则之一。首先申明我们不是攻击JS语言和JS的码农们(惹不起),只是希望以此让大家更加了解JS,写出更好更高效的JS代码来。
1:有问题的ASI实施
ASI机制问题,现在存在争议。JavaScript有一种称为自动分号插入(ASI)的机制,如果需要,会自动在你的代码中插入分号。JS的语言结束可以使用分号;
doSomething();
但是分号可以省略,如果你不添加分号的话,ASI会自动判断,并且自动给你添加上分号。
但是ASI实现是有问题的,如果不是熟悉ASI的机制,某些情况下ASI机制会破坏你的代码,在不该中断地方给你中断,该中断地方又不会中断,就很尴尬了,而且出问题来很难调试。
你可以选择忽略不用它,自己一直添加分号。如果你不想手动敲,则必须熟悉ASI,避免写出引起歧义的语句,以免受边缘情况的影响。
2:有一个怪异的数字类型
与许多其他语言相反,JavaScript有一种称叫做数字类型的单数数字类型。这种类型用于整数和浮点数,对于许多开发人员来说是违反直觉的,绝大多数开发人员都是熟悉的:整数和十进制数字之间有明确区别的语言。
码农需要时常提醒自己到将所有数值操作基于浮点数来处理,并且还需要使用Math对象进行舍入和查找操作的floor()或round(),很多数字操作需要自己专门写函数,很麻烦。下面是保留二位的小数的函数。
此外,类型的数字限制只能使用53位整数,对于更大的整数,你可能需要获取库。
3:三个非值数字:Infinity,-Infinity和NaN
JavaScript有个逻辑"提示,并且继续",无效或无意义的计算(例如除零)不会导致错误或抛出异常,而是产生三个非实数值中的一个,实际上是数字类型:
所以,JS处理数字非常麻烦,并且当涉及到计算繁重的程序时,很难以追踪错误。还需要诸如isFinite,isInteger和isNaN之类的大量方法来做进行数字检查。
4:两个"空"类型:null和undefined
JS事实上有两种不同的null或nil类型,原意是为了更确定区分错误,但可能导致码农在处理时候,反而会增加很多bug。
通常,undefined指的是未初始化的变量或不存在的对象属性,并且指向故意为空的变量或对象属性null,但是如何确定他应该是null或者undefined是个问题。当涉及null用例时,typeof运算符会被破坏
typeof null; // "object"
5:破碎的抽象等式(==)算法
这里真的没什么好说的。 ==运算符背后的抽象等式算法很滑稽,打破了平等和等价关系的数学概念。
它不应该被使用。应该使用严格相等运算符===。
6:不可取的类型强制转化
在处理动态变量和松散输入时,你最终需要执行某种类型强制来完成某些操作。 JavaScript的问题在于引擎所做的隐式类型强制转化是不可取的,非常规的,并且可能导致代码中出现大量错误。
例如,在混合字符串和数字时,+运算符可能会导致一些意外结果:
13 + !0; // 14
"13" + !0; // '13true
更不用说所有这些都是有效但令人费解的语言表达:
作为开发人员,你需要通过包装类构造函数Number,Boolean和String或某些内置解析方法来坚持显式类型强制。
好消息是,被强制转化的值非常容易和直观地记住:"false,null,undefined,NaN,0和''(空)都是逻辑假,其他一切都是true"。
7:var关键字和函数范围
在ES6之后,这已不再是一个问题了。但这是对语言设计不良的证明,十多年来程序员不得不接受这样一个事实,即声明的一个变量是全局性变量。
基本上,你使用var将全局变量引入你的程序中,如果你不小心并且没有真正的块变换范围,这使得理解一些简单的方法就像使用范围一样令人费解。
在ES6之后,现在你应该完全停止使用var,而是使用提供常规块作用域的let和const,并在代码开头引入use strict指令,以防止意外的全局变量声明和其他有问题的运行时行为。
其他一些不是很重要的槽点
简而言之,下面这些只是一些容易遇到而且有学习曲线的小错误,或者只是JavaScript独特语言设计的一个特点,它具有丰富的灵活性和复杂性:
复杂和不良的继承模型
复杂使用this关键字
标准库不佳
我认为任何从Java或C#等语言进入JavaScript的程序员都搞不清JS语言混乱的类语法和用于实现类的复杂对象模型。其中大部分是由于设计不合理的约定和语法决策以适应企业开发人员,因为实际上JavaScript基于原型,而不是类,它的语法应该反映出来,但它确实增加了大多数现有开发人员熟练使用该语言的复杂性。
此外,执行JavaScript的运行时和并发模型在传统编程语言中是相当独特的,因为所有JS代码都是在事件循环运行时中使用事件驱动的非阻塞异步I/O执行的。
最后吐槽的是JavaScript这个名字也是刚开始蹭人热度,后来又非法的存在(JavaScript商标权在Oracle手里),这个在虫虫之前的文章中有提到过,所以避免在自己的产品或者宣传中使用它(已经有开发者收到Oracle的律师函哦),用JS或者正式的名字ECMAScript来替代。