魔鬼的细节:一个对Javascript的十年误解
早上不小心瞟到一篇文章,How Logical AND and OR Operators Actually Work in Javascript,才发现虽然我写了超过10年Javascript,却从来不知道这样的真相!
先说说这个误解,两个常用,及其简单的表达式:
expr1 && expr2
expr1 || expr2
我一直以为以为这是一个标准的boolean表达式,计算后的结果肯定是boolean类型而不会是其他,甚至记得有类似Trick把一个表达式转化为布尔类型。但具体规范让我吓一大跳:
引用
(Logical AND) Returns expr1 if it can be converted to false; otherwise, returns expr2. Thus, when used with Boolean values, && returns true if both operands are true; otherwise, returns false.
引用
(Logical OR) Returns expr1 if it can be converted to true; otherwise, returns expr2. Thus, when used with Boolean values, || returns true if either operand is true; if both are false, returns false.
很多情况下,居然返回的是表达式expr1或expr2的
原值!再仔细想想,上述机制其实也一直在用,只是从没仔细考虑过工作原理,例如
config = config || {x:0, y:0}
我并不因此觉得JavaScript本身有任何问题,只是类似魔鬼细节太多,酷壳上这篇文章深入理解C语言也介绍了许多C语言的陷阱。因此需要我们有更加严谨、谦卑的态度,去做更加深入的学习,例如使用一个语言一段时间后,是否应该去认真的读读语言的规范?
类似误解过去犯过多次,再例如我03年前写的代码中,就有大量的地方在做DCL,类似这样:
private Helper helper = null;
public Helper getHelper() {
if (helper == null) {
synchronized(this) {
if (helper == null) {
helper = new Helper();
}
}
}
return helper;
}
现在我们都知道这个工作理论是有问题的,而且我在系统生产运行中发生的疑难问题,推测就是这个问题引发!
我不知道过去那么多年,写的那么多代码,参与设计的系统,还有传递给他人的知识,究竟有多少是建立在类似错误认识上的?在这么多错误基础上构建的系统,却一直在运行,我只能说,它是一个奇迹!