日期:2014-05-16  浏览次数:20360 次

魔鬼的细节:一个对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;
    }

现在我们都知道这个工作理论是有问题的,而且我在系统生产运行中发生的疑难问题,推测就是这个问题引发!

我不知道过去那么多年,写的那么多代码,参与设计的系统,还有传递给他人的知识,究竟有多少是建立在类似错误认识上的?在这么多错误基础上构建的系统,却一直在运行,我只能说,它是一个奇迹!