《你不知道的javascript》笔记
-
- undefined
- null
- false
- +0、-0 和 NaN
- ""
-
现在我们终于明白 ~ 有什么用处了! ~ 和 indexOf() 一起可以将结果强制类型转换(实际 上仅仅是转换)为真 / 假值:
var a = "Hello World";
~a.indexOf( "lo" ); // -4 // true
if (~a.indexOf( "lo" )) { // 找到匹配!
}~a.indexOf( "ol" );
!~a.indexOf( "ol" );if (!~a.indexOf( "ol" )) { // true 没有找到匹配!
}
如果 indexOf(..) 返回 -1,~ 将其转换为假值 0,其他情况一律转换为真值。稍微说下,实际中用到这个可能会被打。至少我还没有遇到过这种的代码
-
~~x 能将值截除为一个 32 位整数,x | 0 也可以,而且看起来还更简洁。
出于对运算符优先级(详见第 5 章)的考虑,我们可能更倾向于使用 ~~x。
我们在使用 ~ 和 ~~ 进行此类转换时需要确保其他人也能够看得懂。
-
常见的误区是“== 检查值是否相等,=== 检查值和类型是否相等”。
正确的解释是:“== 允许在相等比较中进行强制类型转换,而 === 不允许。”
-
var i = 2;
Number.prototype.valueOf = function() {
return i++;
};
var a = new Number(42);
if (a == 2 && a == 3) {
console.log( "Yep, this happened." );
}之前遇到这个面试题,就感觉很神奇,可能就是从这本书里搞到的这种有点算是刁难的面试题吧。
-
JSON 被普遍认为是 JavaScript 语言的一个真子集,
js{"a":42}
这样的 JSON 字符串会被当作合法的 JavaScript 代码(请注意 JSON 属性名必须使用双引号!)。其实不是!如果在控制台中输入js{"a":42}
会报错。因为标签不允许使用双引号,所以 "a" 并不是一个合法的标签,因此后面不能带 :。
JSON 的确是 JavaScript 语法的一个子集,但是 JSON 本身并不是合法的 JavaScript 语法。
经过我的测试,在Google和Safra中都不会报错,在Firefox中确实报错,IE的话,对不起我没有这个浏览器
-
尤其要提出的是,在某些条件下,某些浏览器的 console.log(..) 并不会把传入的内容立 即输出。出现这种情况的主要原因是,在许多程序(不只是 JavaScript)中,I/O 是非常低 速的阻塞部分。所以,(从页面 /UI 的角度来说)浏览器在后台异步处理控制台 I/O 能够提 高性能,这时用户甚至可能根本意识不到其发生。
var a = {
index: 1
};
// 然后
console.log( a ); // ??
// 再然后 a.index++;我们通常认为恰好在执行到
js console.log(..)
语句的时候会看到 a 对象的快照,打印出类 似于js{ index: 1 }
这样的内容,然后在下一条语句jsa.index++
执行时将其修改,这句的执 行会严格在 a 的输出之后。多数情况下,前述代码在开发者工具的控制台中输出的对象表示与期望是一致的。但是, 这段代码运行的时候,浏览器可能会认为需要把控制台 I/O 延迟到后台,在这种情况下, 等到浏览器控制台输出对象内容时,
jsa.index++
可能已经执行,因此会显示js{ index: 2 }
。到底什么时候控制台 I/O 会延迟,甚至是否能够被观察到,这都是游移不定的。如果在调 试的过程中遇到对象在
jsconsole.log(..)
语句之后被修改,可你却看到了意料之外的结果, 要意识到这可能是这种 I/O 的异步化造成的。console是可能被阻塞的,好吧,我之前不知道,不过我也确实不经常用console来调试,我更习惯打断点。
-
我们在假装并行执行多个任务时,实际上极有可能是在进行快速的上下文切换,比如与朋 友或家人电话聊天的同时还试图打字。换句话说,我们是在两个或更多任务之间快速连续 地来回切换,同时处理每个任务的微小片段。我们切换得如此之快,以至于对外界来说, 我们就像是在并行地执行所有任务。
这听起来是不是和异步事件并发机制(比如 JavaScript 中的形式)很相似呢?!如果你还 没意识到的话,就回头把第 1 章再读一遍吧!
实际上,把广博复杂的神经学简化(即误用)为一种这里我足以讨论的形式就是,我们大 脑的工作方式有点类似于事件循环队列。
如果把我打出来的每个字母(或单词)看作一个异步事件,那么在这一句中我的大脑就有 几十次机会被其他某个事件打断,比如因为我的感官甚至随机思绪。
我不会在每次可能被打断的时候都转而投入到其他“进程”中(这值得庆幸,否则我根本 没法写完本书!)。但是,中断的发生经常频繁到让我觉得我的大脑几乎是不停地切换到 不同的上下文(即“进程”)中。很可能 JavaScript 引擎也是这种感觉。
其实看起来很强大的引擎、编译器、应用等,底层原理往往没有想象中复杂,缓存和事件循环往往是底层的一些原理,其实任何事情都是有代价的,算法就是用代码复杂度来换空间或者事件的复杂度,有些时候我们有需要用时间复杂度去换空间复杂度,或者相反,但是原理总是那些。
-
唯一比不知道代码为什么崩溃更可怕的事情是,不知道为什么一开始它是工 作的!这就是经典的“纸牌屋”心理:“它可以工作,可我不知道为什么, 所以谁也别碰它!”你可能听说过“他人即地狱”(萨特)这种说法,对程 序员来说则是“他人的代码即地狱”。而我深信不疑的是:“不理解自己的代 码才是地狱。”回调就是主要元凶之一。
-
回调最大的问题是控制反转,它会导致信任链的完全断裂。
现代的计算机基础都是基于约定和信任建立起来的,我们很多时候不得不信任数据,即使有基本的判断也并不能完全判定通过,所以信任别人,但是要做基本的防错。