浅谈 JavaScript

JavaScript 是一门优秀的编程语言吗?

每个人可能观点并不完全一致,但是从很多角度来看,JavaScript 是一门非常优秀的编程语言;
而且,可以说在很长一段时间内这个语言不会被代替,并且会在更多的领域被大家广泛使用;

著名的 Atwood 定律:

Stack Overflow 的创立者之一的 Jeff Atwood 在 2007 年提出了著名的 Atwood 定律。

any application that can be written in JavaScript, will eventually be written in JavaScript.

任何可以使用 JavaScript 来实现的应用都最终都会使用 JavaScript 实现。

其实我们已经看到了,这句话正在一步步被应验:

  • Web 端的开发我们一直都是使用 JavaScript;
  • 移动端开发可以借助于 ReactNative、Weex、Uniapp 等框架实现跨平台开发;
  • 小程序端的开发也是离不开 JavaScript;
  • 桌面端应用程序我们可以借助于 Electron 来开发;
  • 服务器端开发可以借助于 Node 环境使用 JavaScript 来开发。

JavaScript 的痛点

并且随着近几年前端领域的快速发展,让 JavaScript 迅速被普及和受广大开发者的喜爱,借助于 JavaScript 本身的 强大,也让使用 JavaScript 开发的人员越来越多。

优秀的 JavaScript 没有缺点吗?

其实上由于各种历史因素,JavaScript 语言本身存在很多的缺点;

比如 ES5 以及之前的使用的 var 关键字关于作用域的问题;

比如最初 JavaScript 设计的数组类型并不是连续的内存空间;

比如直到今天 JavaScript 也没有加入类型检测这一机制;

JavaScript 正在慢慢变好

不可否认的是,JavaScript 正在慢慢变得越来越好,无论是从底层设计还是应用层面。

ES6、7、8 等的推出,每次都会让这门语言更加现代、更加安全、更加方便。

但是知道今天,JavaScript 在类型检测上依然是毫无进展(为什么类型检测如此重要,我后面会聊到)。

类型带来的问题

首先你需要知道,编程开发中我们有一个共识:错误出现的越早越好

能在写代码的时候发现错误,就不要在代码编译时再发现(IDE 的优势就是在代码编写过程中帮助我们发现错 误)。

能在代码编译期间发现错误,就不要在代码运行期间再发现(类型检测就可以很好的帮助我们做到这一点)。

能在开发阶段发现错误,就不要在测试期间发现错误,能在测试期间发现错误,就不要在上线后发现错误。

现在我们想探究的就是如何在 代码编译期间 发现代码的错误:

JavaScript 可以做到吗?不可以,我们来看下面这段经常可能出现的代码问题。

1
2
3
4
5
6
7
function getLength(str){
console.log(str.length)
}

getLength('abc')
getLength()
// 报错: Uncaught TypeError: Cannot read properties of undefined (reading 'length')

这是我们一个非常常见的错误:

这个错误很大的原因就是因为 JavaScript 没有对我们传入的参数进行任何的限制,只能等到运行期间才发现这个 错误;
并且当这个错误产生时,会影响后续代码的继续执行,也就是整个项目都因为一个小小的错误而深入崩溃;

当然,你可能会想:我怎么可能犯这样低级的错误呢?

当我们写像我们上面这样的简单的 demo 时,这样的错误很容易避免,并且当出现错误时,也很容易检查出来;

但是当我们开发一个大型项目时呢?你能保证自己一定不会出现这样的问题吗?而且如果我们是调用别人的类

库,又如何知道让我们传入的到底是什么样的参数呢?

但是,如果我们可以给 JavaScript 加上很多限制,在开发中就可以很好的避免这样的问题了:

比如我们的 getLength 函数中 str 是一个必传的类型,没有调用者没有传编译期间就会报错;

比如我们要求它的必须是一个 String 类型,传入其他类型就直接报错;

那么就可以知道很多的错误问题在编译期间就被发现,而不是等到运行时再去发现和修改;

类型思维的缺失

我们已经简单体会到没有类型检查带来的一些问题,JavaScript 因为从设计之初就没有考虑类型的约束问题,所以

造成了前端开发人员关于类型思维的缺失:

前端开发人员通常不关心变量或者参数是什么类型的,如果在必须确定类型时,我们往往需要使用各种判断验 证;

从其他方向转到前端的人员,也会因为没有类型约束,而总是担心自己的代码不安全,不够健壮;

所以我们经常会说 JavaScript不适合开发大型项目,因为当项目一旦庞大起来,这种宽松的类型约束会带来非常多 的安全隐患,多人员开发它们之间也没有良好的类型契约。

比如当我们去实现一个核心类库时,如果没有类型约束,那么需要对别人传入的参数进行各种验证来保证我们 代码的健壮性;

比如我们去调用别人的函数,对方没有对函数进行任何的注释,我们只能去看里面的逻辑来理解这个函数需要 传入什么参数,返回值是什么类型;

为 JavaScript 添加类型约束的好处

背景:JS 的类型系统存在“先天缺陷“,代码中绝大部分错误都是类型错误(Uncaught TypeError )。
问题 ∶ 增加了找 Bug、改 Bug 的时间,严重影响开发效率。

从编程语言的动静来区分

TypeScript 属于静态类型的编程语言,JS 属于动态类型的编程语言

静态类型︰编译期做类型检查;动态类型 ∶ 执行期做类型检查。

代码编译和代码执行的顺序 ∶1 编译,2 执行。

对于 JS 来说 ∶ 需要等到代码真正去执行的时候才能发现错误(晚)。

对于 TS 来说 ∶ 在代码编译的时候(代码执行前)就可以发现错误(早)。

并且,配合 VSCode 等开发工具,TS 可以提前到在编写代码的同时就发现代码中的错误,减少找 bug、改 bug 时间

Ts 相比 Js 的优势

  • 更早(写代码的同时)发现错误,减少找 Bug、改 Bug 时间,提升开发效率。
  • 程序中任何位置的代码都有代码提示,随时随地的安全感,增强了开发体验。
  • 强大的类型系统提升了代码的可维护性,使得重构代码更加容易。
  • 支持最新的 ECMAScript 语法,优先体验最新的语法,让你走在前端技术的最前沿。
  • TS 类型推断机制,不需要在代码中的每个地方都显示标注类型,让你在享受优势的同时,尽量降低了成本。
  • 除此之外,Vue 3 源码使用 TS 重写、Angular 默认支持 TS、React 与 TS 完美配合,TypeScript 已成为大中型前端项目的首选编程语言

为了弥补 JavaScript 类型约束上的缺陷,增加类型约束,很多公司推出了自己的方案:

2014 年,Facebook 推出了 flow 来对 JavaScript 进行类型检查;

同年,Microsoft 微软也推出了 TypeScript1.0 版本;

他们都致力于为 JavaScript 提供类型检查;

而现在,无疑 TypeScript 已经完全胜出:

Vue2.x 的时候采用的就是 flow 来做类型检查;

Vue3.x 已经全线转向 TypeScript,98.3%使用 TypeScript 进行了重构;

而 Angular 在很早期就使用 TypeScript 进行了项目重构并且需要使用 TypeScript 来进行开发;

而甚至 Facebook 公司一些自己的产品也在使用 TypeScript;

学习 TypeScript 不仅仅可以为我们的代码增加类型约束,而且可以培养我们前端程序员具备类型思维。

TypeScript 介绍

TypeScript 介绍

虽然我们已经知道 TypeScript 是干什么的了,也知道它解决了什么样的问题,但是我们还是需要全面的来认识一下 TypeScript 到底是什么?

们来看一下 TypeScript 在 GitHub 和官方上对自己的定义:

GitHub 说法:TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

TypeScript 官网:TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.

翻译一下:TypeScript 是拥有类型的 JavaScript 超集,它可以编译成普通、干净、完整的 JavaScript 代码。

怎么理解上面的话呢?

我们可以将 TypeScript 理解成加强版的 JavaScript。

JavaScript 所拥有的特性,TypeScript 全部都是支持的,并且它紧随 ECMAScript 的标准,所以 ES6、ES7、ES8 等新语法标准,它都是 支持的;

并且在语言层面上,不仅仅增加了类型约束,而且包括一些语法的扩展,比如枚举类型(Enum)、元组类型(Tuple)等;

TypeScript 在实现新特性的同时,总是保持和 ES 标准的同步甚至是领先;

并且 TypeScript 最终会被编译成 JavaScript 代码,所以你并不需要担心它的兼容性问题,在编译时也不需要借助于 Babel 这样的工具;

所以,我们可以把 TypeScript 理解成更加强大的 JavaScript,不仅让 JavaScript 更加安全,而且给它带来了诸多好用的好用特性;

TS 初体验

Ts 的编译环境

在前面我们提到过,TypeScript 最终会被编译成 JavaScript 来运行,所以我们需要搭建对应的环境:

我们需要在电脑上安装 TypeScript,这样就可以通过 TypeScript 的 Compiler 将其编译成 JavaScript;

TypeScript 2

所以,我们需要全局安装

安装命令

npm install typescript -g

查看版本

tsc –version

TS 的运行环境

如果我们每次为了查看 TypeScript 代码的运行效果,都通过经过两个步骤的话就太繁琐了:

第一步:通过 tsc 编译 TypeScript 到 JavaScript 代码;

第二步:在浏览器或者 Node 环境下运行 JavaScript 代码;

是否可以简化这样的步骤呢?

比如编写了 TypeScript 之后可以直接运行在浏览器上?

比如编写了 TypeScript 之后,直接通过 node 的命令来执行?

上面我提到的两种方式,可以通过两个解决方案来完成:

方式一:通过 webpack,配置本地的 TypeScript 编译环境和开启一个本地服务,可以直接运行在浏览器上;

  • npm init –y
  • npm i webpack webpack-cli –D
  • npm i ts-loader typescript –D
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const path = require('path')
module.exports = {
entry: './src/index.ts',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
resolve: {
extensions: ['.tsx','.ts', '.js']
},
module: {
rules: [
{
test: /.ts$/,
loader: 'ts-loader',
exclude: /node_modules/
}
]
}
mode: 'development'
}

其它配置项参考webpack章节 ~

方式二:通过 ts-node 库,为 TypeScript 的运行提供执行环境;

安装 npm install -g ts-node

另外 ts-node 需要依赖 tslib 和 @types/node 两个包:

npm install tslib @types/node -g

现在,我们可以直接通过 ts-node 来运行 TypeScript 的代码:

ts-node index.ts

注意:ts-node 7.0.0 以上就不自动识别 tsconfig.json 了,得加上 –files 才能识别

ts-node index.ts –files