做一个好前端必须要知道的事——JS语言
编程语言按各种方法可以分为各种类型,现在让我们来看看JS属于什么类型语言
解释型语言
按编译执行过程,可以分为编译型语言和解释型语言。比如
- c 语言,必须先经过编译生成目标文件,然后链接各个目标文件和库文件,生成可执行文件。
- Java、scala 则是先编译成字节码,然后解释执行字节码(可以理解为编译型语言也可以理解为解释型语言)。准确的理解,java 是编译型语言,源代码整个编译成字节码,java 字节码,是解释型语言。
- Python 是解释型语言,不过也可以先进行编译,编译成 python 的字节码。
- Javascript 是解释型语言。目前貌似还没有直接将 js 整个编译然后才执行(有说法是 js 动态性太强,先整体编译难度太大,执行性能不如解释执行高)。
⚠️注意:解释型语言也是需要编译的。区分编译型语言和解释型语言,是看源代码是否整个编译成目标代码然后执行还是编译一段执行一段。
对于传统编译型语言来说,编译步骤分为:词法分析、语法分析、语义检查、代码优化和字节生成。
但对于解释型语言来说,通过词法分析和语法分析得到语法树后,就可以开始解释执行了(根据语法树和符号表生成机器码)。
这也就解释了为什么都说 js 是解释执行的,读一句执行一句,但是实际上 js 中还没执行到的代码语法错误导致整个 js 不会执行的问题。例如:
console.log('不会被console出来');
= // 这里的语法错误导致了上面的代码也不会执行
其实js变量提升的现象也很明显的证明了js是先编译而后执行的
在浏览器中,多个‹script›标签中的 js 代码,是分段编译的(所以,某一个‹script›标签中的语法错误不会导致另一个‹script›中的代码不执行)但是全局对象是共享的。
动态语言
按语言按变量的类型在编译时确定还是运行时确定可以分为静态语言和动态语言。比如
- java,String s = null; 变量 s 的类型在编译时就可以确定为字符串类型。
- python,变量不需要声明,变量的类型在第一次赋值时由值的类型确定。
- js,let val;let = ‘1’; 变量 val 在运行 val=’1’时才能确定为字符串类型。
弱类型语言
按变量的类型是否在运行时可以改变分为强类型语言和弱类型语言。比如
- Java、scala 是强类型语言,变量一旦声明,它的类型以后不能被改变。
- Python 是强类型语言。
- Js 是弱类型语言。比如 let v = ‘1’;v=1;v=true;这在 js 中是合法的。
非常灵活的语言
按语言范式可以分为声明式、命令式、函数式语言。
- 声明式编程,告诉计算机我要做什么,而不是如何做。在更高层面写代码,更关心的是目标,而不是底层算法实现的过程。例如 css, 正则表达式,sql 语句,html, xml…
- 命令式编程,告诉计算机如何做,而不管我想要做什么。解决某一问题的具体算法实现。例如 java、c。
- 函数式编程,将计算机运算看做是数学中函数的计算,并且避免了状态以及变量的概念。
- 很多语言并不是单纯的支持某一种范式,像 java8 也添加了部分对函数式的支持。
- js 是一个非常灵活的语言,支持命令式和函数式编程。
各种类型语言的优缺点
- 一般编译型语言性能比解释型语言高。但是由于编译型语言需要先进行编译。
- 解释型语言的好处是,部署到线上的是源代码,可以直接修改线上环境的代码,解决一些 bug。比如我们有时候直接修改线上的 js 代码。
- 编译型语言通常会用 xml 做配置文件,因为我们通常不会改编译后的字节码。解释型语言的配置,直接写在源代码里更方便,用 xml 做配置就显得多余。
- 静态语言,有利于编译时检查。比如 java、在 ide 中为对象的一个不存在的属性赋值能在编译时检查出错误。
- Js 是动态语言。对象的某个属性是否存在,在编译时无法确定。这导致某些错误要到运行时才可能发现。所以一般 js 程序的正确性,更需要单元测试保证。
- 强类型语言由于类型在声明之后不允许改变,所以能实现编译时类型检查。动态语言和弱类型语言,则更灵活,实现相同功能的代码量通常更少或者更容易实现复杂功能。当然可读性可维护性方面不如静态语言和强类型语言。