作者:道格拉斯 · 克罗克福德
译者:死月(朱凯迪)
命名
- 【不推荐】以下划线_开头或结尾命名:通常是为了表示私有属性或者全局私有变量
- 【不推荐】美元符号$:通常是被一些代码生成器、转义器和宏处理器加到变量里,保证生成的变量名不会与人工编写的代码冲突。
- 【推荐】所有构造函数名以大写字母开头,而其他任何名字都以小写字母开头
数值
- IEEE 754标准,64位浮点数类型。1位符号位(0为正,1为负),11位指数位,52位有效位(默认开头为1,实际53位有效)
- 浮点数的思想:把一个数拆成两部分存储
- 第一部分是有效位数significand(或者也叫系数coefficient、分数fraction、尾数mantissa)
- 第二部分是指数exponent,表示小数点应该插在有效位数的哪个位置。
布尔类型
- 除了真 true 和假 false,还有幻真 truthy 和 幻假 falsy
- 幻假 falsy: false、null、undefined、“”(空字符串)、0、NaN
- 幻真 truthy:其余都是
非类实例对象
- 构造函数就是返回对象的函数。它的参数和变量会成为所返回对象的私有属性,没有公有属性。构造函数内的一些函数则会成为返回对象的方法。私有属性被关在闭包内,而公有的方法则被打包进返回的冻结对象中
尾调用
- 尾调用:函数的返回值是另一个函数的直接返回值。
- try块中不能进行尾调用优化。catch会重新生成一个作用域,激活对象不能被缩减
- 函数内部创建了新函数对象,这个新函数用到了自由变量(闭包),则也不能被缩减
纯度
事件化编程
- 顺序化编程语言的一个典型特定就是会阻塞输入输出
- 并发
- 同构并发:同时处理多个类似操作,比如数组提供一个纯函数,可以操作所有元素
- 异构并发:支持各种不同职责逻辑项的协作,使其能像一个团队一样齐心协力
- 事件函数是一种会立即返回的函数,可能在其要求的工作完成前就返回。它的结果通常
- JS是单线程的。大部分状态不在栈上,而是存在函数的闭包中
- 事件循环机制
日期
JSON
- JSON(JavaScript Object Notation)的名称由来。
- 如果对象中包含一个toJSON方法,那么就会执行toJSON自身的方法。一般而言JSON.stringify就会调用该方法
- JSON.stringify的可选参数replacer:
- 如果是个函数,它接收键名和键值,并为键名返回最终值
- 如果是一个字符串数组,则只有数组中的属性才会被转换(过滤器)
测试
- 我们只能证明程序存在缺陷,但不能证明它没有缺陷
- bug就是混乱的同义词。消除混乱比测试更能提高生产力
- 平时养成多删代码的习惯。在预估开发周期时,务必为删除多余代码、淘汰有问题的依赖包预留时间
- 假阴性总是可以被迅速发现和修复,而假阳性则可长期藏身
- 随着纯度的下降,bug就开始增加,而单元测试并不测试代码纯度
优化
- 我们应当只优化那些有显著成效的地方
- 优化的目的是节省时间,我们必须优化我们的优化
- 一种非常普遍的实践就是比较一门语言的两种特性,做法是将其分别写入循环,然后度量循环时间。这种方式有问题:
- 测试特性性能,还是引擎的优化程度
- 结果可移植吗
- 其他引擎能否有一样的结果
- 结果未来会变吗
- 在编程届:一思而后行,温故而知新
- 现在的代码几乎都不存在性能问题,在非性能瓶颈处优化代码就是浪费生命
- 低性能元凶:
- 无法并行化
- 违反回合法则
- 低内聚性
- 高耦合性
- 错误算法
- 缓存抖动
- 代码膨胀
- 第三方代码
- 网络资源顺序加载,而非管道加载
- 效率极低的DOM API
转译
- 转译是一种特殊的编译,它将一种编程语言转换为另一种编程语言。
- 转译器的优势(如babel)
- 实验
- 特定化
- 兼容旧版
- 时髦
- 先行
- 安全(移除不安全的特性)
- 性能(支持ASM、WASM等)
- 永远不要在生产环境使用转译器
- 下一门语言应该满足的特点:
- 对统一码有更好的支持
- 使用UTF-32作为字符的内部表现形式
- 对二进制大对象(binary large object,Blob)的直接支持
- 对事件化编程有更好的支持
- 对安全网络有更好的支持
- 对进程管理有更好的支持,包括启动、通信和销毁
- 支持纯函数的并行处理
编译器原理
- 分词(划分各种token)
- 解析(将token转换为AST)
- 代码生成
- 运行时:用于执行程序的软件
- 如果一门源语言与其目标语言在语义上存在差异,就需要一些特殊的运行时支持