JavaScript中好的那部分

发表于更新于阅读时长 6 分钟

关于<<JavaScript: The Good Parts>>

现在已经是 9210 年, DC, or that json guy究竟对前端业界起到了什么作用, 我相信任何读者心里都有自己的评价. 但这并不意味着他写的书不值得一读, 本文大体上就<<JavaScript: The Good Parts>>的读书笔记, 以及, 我心中 JavaScript 好的部分

第一章 精华

JavaScript 是第一个成为主流的 Lambda 语言 它是披着 C 外衣的 Lisp

hmmm

现今大部分编程语言中都流行要求强类型

静态类型

但事实证明,强类型并不会让你的测试工作变得轻松

可能因为当时的静态语言太弱或者不静态

我发现弱类型是自由的

这倒是真的

JavaScript 有非常强大的对象字面量表示法...这种表示法是 JSON 的灵感来源

也是 DC 做的少数好事之一

第二章 语法

这个列表不包括一些本应该被保留而没有保留的字,诸如 undefined、NaN 和 Infinity

本就不需要

这提供了很大的方便,因为它完全避免了短整型的溢出问题

那可以不提供短整型, 内置整数类型像 python 那样默认提供高精度运算就完了

JavaScript 没有字符类型

这点做对了

如果运算数是一个数组或 null,那么结果是'object',这其实是不对的

真是遗憾

第三章 对象

我们将给 Object 增加一个 create 方法

DC 做的另一件好事

如果我们尝试去获取对象的某个属性值,但该对象没有此属性名,那么 JavaScript 会试着从原型对象中获取属性值...最后到达终点 Object.prototype...这个过程称为委托。

JS 中的继承实际是动态委托. 当然也可以说类继承实际上是静态委托

属性名出现的顺序是不确定的

no more!

第四章 函数

这被称为闭包(closure)。它是 JavaScript 强大表现力的来源

正是如此

当实际参数的个数与形式参数的个数不匹配时,不会导致运行时错误

JS 的另一个优点

以此模式调用函数时,this 被绑定到全局对象。这是语言设计上的一个错误。

的确. 好在箭头函数修正了这一点

如果调用构造器函数时没有在前面加上 new,可能会发生非常糟糕的事情,既没有编译时警告,也没有运行时警告

考虑到把一个函数同时当构造器和普通函数的情况非常罕见, 这不是特别好的设计

因为语言的一个设计错误,arguments 并不是一个真正的数组

好在当代不会造成什么问题

如果函数调用时在前面加上了 new 前缀,且返回值不是一个对象,则返回 this

这个细节实际上还有点用

因为 JavaScript 原型继承的动态本质,新的方法立刻被赋予到所有的对象实例上,哪怕对象实例是在方法被增加之前就创建好了

对于 90 年代的脚本语言来说确实不错

糟糕的是,尽管 JavaScript 的代码块语法貌似支持块级作用域,但实际上 JavaScript 并不支持

再次感谢 ES6

我们可以使用函数和闭包来构造模块

现在还在用, 真是惨

如果我们让这些方法返回 this 而不是 undefined,就可以启用级联

或者用 pipe

柯里化

没啥大用

第五章 继承

return (typeof other === 'object' && other) || that

还注意到了 other 是 null 的情况

我们可以构造另一个伪类来继承 Mammal Cat.prototype = new Mammal()

现在可以用 Object.create 了

现在多个参数可以按任何顺序排列,如果构造器会聪明地使用默认值,一些参数可以忽略掉,并且代码也更容易阅读

是的, 而且还可以实现 named parameter

函数化

概括一下, constructor(spec, my), 方法在函数体里生成, spec 里装在外界调用构造器时传入的属性, my 里装准备塞给继承链中父级的属性

简而言之就是又反直觉又没用

如果想构造一个私有属性,他们就给它起一个怪模怪样的名字,并且希望其他使用代码的用户假装看不到这些奇怪的成员

其实挺好的

在伪类模式里,构造器函数 Cat 不得不重复构造器 Mammal 已经完成的工作

哦是吗

该对象的属性可以被替换或删除,但该对象的完整性不会受到损害

说的好, 但这毫无意义

部件

现在可以用 Mixin, 而且它快进标准了

第六章 数组

不幸的是,JavaScript 没有像此类数组一样的数据结构

不幸的是, JavaScript 有

你可以直接设置 length 的值。设置更大的 length 不会给数组分配更多的空间

JS 又一个设计缺陷

typeof 运算符报告数组的类型是'object',这没有任何意义

但是 JS 中的数组本来就是对象, 这是设计时做对的事情之一

JavaScript 没有一个好的机制来区别数组和对象

ES5 里终于有了 Array.isArray

Object.prototype.toString.apply(value)

传统黑魔法, 现在还用于判断Object.create(null)

第七章 正则表达式

regular expressions

source: xkcd

第八章 方法

方法

为什么不在对应的章节里讲...

shift 通常比 pop 慢得多

那当然...

如果我们想要给任何包含简单值的数组排序

but why

sort 方法是不稳定的

时过境迁, 随着这个 PR, 现在 JS 里的 sort 是稳定的了

charCodeAt 如果 pos 小于 0 或大于等于字符串的长度 string.length,它返回 NaN

这可真蠢

这个方法主要用在土耳其语上,因为在土耳其语中‘i’转换为‘İ’,而不是‘I’

原来如此...

第九章 代码风格

在诸如 if 和 while 这样结构化的语句里,我始终使用代码块

一行能写下的话我觉得没有必要

JavaScript 允许变量在它们使用后被声明。那对我来说感觉像是一个错误

'use strict'是好东西

我绝不在一个 if 的条件部分使用赋值表达式

是个好习惯

第十章 优美的特性

基于原型继承的动态对象

原型既无用又难以优化, 动态对象是好东西

如果产品和编程语言被设计得仅留下精华,那该有多好

是啊...

附录 A 毒瘤

附录 A

塞在附录里并不会让他们不存在

JavaScript 没有链接器

谢天谢地, 终于有了, 虽然都不怎么好用

return
{
  status: true
} // will return undefined

这真是个恶劣的设计

parseInt 如果该字符串第 1 个字符是 0,那么该字符串会基于八进制而不是十进制来求值

ES5 修正了这个错误

这个复杂的行为是 bug 的常见来源

也是 JS 用于 web 开发的方便之处

但它们的性能相比真正的数组可能相当糟糕

除非你故意这么做

NaN 是 falsy 的

这个设计真是神秘

附录 B 糟粕

附录

又来...

我的建议是永远不要使用==和!=

我也这么建议

with 语句在这门语言里存在,本身就严重影响了 JavaScript 处理器的速度,因为它阻断了变量名的词法作用域绑定。它的本意是好的,但如果没有它,JavaScript 语言会更好一点

是这样的

我发现一段代码通过重构移除 continue 语句之后,性能都会得到改善

针对特定实现的过早优化

当我使用++和--时,代码往往变得过于拥挤、复杂和隐晦

那是你的问题

在大多数语言中,这些位运算符接近于硬件处理,所以非常快。但 JavaScript 的执行环境一般接触不到硬件,所以非常慢

这可真是时代局限

这放宽了函数必须先声明后使用的要求,而我认为这会导致混乱

wait what

结果表明大多数的浏览器都允许在 if 语句里使用 function 语句,但它们在解析时的处理上各不相同。这就造成了可移植性的问题。

居然直到今天还是这样...

而在 JavaScript 里,void 是一个运算符,它接受一个运算数并返回 undefined。这没有什么用,而且令人非常困惑

事实上, 用 void 可以在一些情况下避免写分号, 以获得全文一致性

附录 C JSLint

反正已经 dead 了

附录 D 语法图

真的会有人看这个吗

附录 E JSON

所以可以被人和机器阅读。它易于实现且易于使用

JSON 真是个方便的工具, 然而因为发明者的偏见, 它可笑地缺乏很多功能, JSON 的广泛使用更使得它从仅仅是数据交换工具, 变成了很多时候由人类来阅读和书写的工具, 这就进一步凸显了它的问题. 而实现这些功能又是如此的简单, 随便什么人花费一点点时间就能把它们补上, 这就造成了标准的进一步分裂. 时至今日, 我们已经有了无数的 JSON 变种, 它们中最出名的一些包括 JSONC JSON5 JSON6 YAML, 以及其他种种 JSON 解析器中不那么标准的部分, 假如发明者有一些远见, 它们都将不复存在

因为 JSON 就是 JavaScript

直到当代都不是

© 2016 - 2023Austaras Devas