JavaScript 的好与坏

May 09, 2023

道格拉斯的观点

JSON 发明者,《JavaScript 语言精粹》作者

观点1

If a feature is sometimes useful and sometimes dangerous and if there is a better option then always use the better option.

如果一个特性有时好用有时危险,还有一个更好的选项,那么我们总是应该使用哪个更好的。

观点2

We are not paid to use every feature of a language. We are paid to write programs that works well and are free of error.

公司雇我们不是为了让我们使用语言的每个特性,而是让我们写出可以用的代码,并且避免错误。

根据以上两个观点,得到结论:我们是不是有可能,只用 JS 好用的部分呢?如果我们坚持使用 JS 好用的部分,我们就可以避免 JS 本身带来的 Bug

保守派之反驳

这个时候,就会有人这么说:

  • 为什么 JS 要把那些特性给我们呢?那就是因为觉得我们需要 JS 有这些特性才要给我们的,或者有这么一句话 —— 存在即合理
  • JS 有这些特性,肯定是有他一定得理由,那我们为什么要反对去用它呢?

那不得不说说程序员的共识:

  • 我们程序员是在不断进化的,我们现在学到的知识是进化了几十年后的效果
  • 就像人类一样,人类现在在上小学的时候,都知道地球是圆的(虽然严格来说并不是),但是在过去几千年里,人类都不知道地球是圆的
  • 那么程序员也是一样的,现在的程序员在刚入门的时候,就知道面向对象是好的、高级语言是好的等等,这些东西你一入门就知道,但是以前的程序员要不断地进行达成共识

程序员的共识

那么怎么达成的呢?让我们回顾过去 50 年的历史

1960 年代

程序员花了一代人的时间去认同「高级语言是好的」(反方:机器语言效率高)

高级语言就是现在用的 JavaScript、Java、C++、Python、Ruby 等…
但「这些语言是好的」这件事情,在曾经不被认可
他们认为:汇编、机器语言才是最好的,因为省内存、效率高,如果使用高级语言,光是解析这些语言,就要占用一半以上内存,剩下的内存就不够用了(因为 1960 年计算的内存 2MB 就已经算非常大了)

跟随着机器的内存不断提高,并且用了这些语言之后发现很好用,所以就认同了这个观点

1970 年代

程序员花了一代人的时间去认同「goto 是不好的」

因为 goto 会被滥用,所以程序员们达成了共识,所以在很多语言中就尽量少用 goto(在 JavaScript 中,是不支持 goto 的,虽然有个 goto 半成品:可以在 break 中使用)

对应的就支持 —— 「结构化编程」

一个编程语言只需要支持 3 种结构:子程序for 循环if

也就是:顺序执行语句条件语句循环语句,只要有这 3 中语句,贝尔梅尔这门编程语言就是完整的

1980 年代

反对以前那种松散的面条式代码

程序员花了一代人的时间去认同「对象是好的」,发展 面向对象

现在 JS 默认是有对象的,但是在很早之前,在 C 语言那个时候,大家都不用对象,这个时候发明 Java 的程序员在那个时候就开始研究设计模式,开始研究面向对象(那个时候 Java 还没出生),把面向对象研究得很成熟之后,Sun 公司才推出了 Java 这门语言

1990 年代

程序员花了 20 年的时间去认同「lambda 表达式是好的」,这件事情在目前估计还没有完全认同

lambda 在 JS 中,lambda 表达式是匿名函数
「匿名函数是个好东西」 这句话如果说给 JS 程序员听,就不会有什么特别感觉,觉得挺好的
而说给 Java、C++ 程序员,他们就不会有跟我们一样的感觉,就会觉得 会更好呀,为什么我们要使用 lambda 表达式 呢?

在后面版本,Java、C++、PHP、Python 都加入了 lambda 表达式,不使用之前过于复杂的面向对象的设计,而是用更轻量的匿名函数和闭包的形式来写我们的程序

那些不对的观点

存在即合理

比如 JS 中的:var==

代码越短越好

并不完全错误,「无歧义」优于「简洁」

代码虽然写得短,但有可能不同的人有不同的理解,那这样就不好了

例如:

1
let fn = x => {name: x}

如果以上代码我这样调用:fn('John'),很多新手就会以为输出 John,其实是 undefind
那么如何解决呢?请这么修改

1
let fn = x => ({name: x})

所以,有时候会造成歧义,但是这个歧义不是人造成的,是 JS 造成的

JS 代码中的特性取舍

基本原则:能完成特定功能,并且无歧义、无副作用,这样的特性,优先使用

不要用的 JS 特性

  • 绝对不要用

    • 全局变量(如果有1万个全局变量?)

    • var
      有 Bug,会变量提升;
      有副作用,声明后会挂载到 window

    • ==

      1
      [] == 0, "0" == 0, [] != "0"
    • 包装类型 String、Boolean

      1
      2
      3
      4
      5
      6
      7
      var x = new String(false)

      if(x) {
      console.log('hi')
      } else {
      console.log('ho')
      }

      会输出 hi,因为 x 是一个对象,JS 中所有的对象都是 true

  • 有些人不用

    • class、new、this
    • 比如喜欢 React Hooks 的开发者
  • 用的人不多,尽量少用

    • symbol、generator、iterator
    • 反射

一定要用的 JS 特性

  • ===

  • ... 运算符

  • 模块 importexport

  • let const

  • 析构赋值

  • Promiseawait

可以使用的 JS 特性

  • class

  • gettersetter

  • WeakMap

  • Proxy

存在问题但可以用

  • 箭头函数

  • 数组 API + Polyfill

感谢阅读,下次见 :)

OLDER > < NEWER
cd ../