类型系统java
类型安全 —— 强类型 VS. 弱类型python
类型检查 —— 静态类型 VS. 动态类型编程
为何JS是弱类型且动态类型呢?安全
关于查资料对于编译型语言和解释型语言的知识点补充编程语言
这篇文章要先讨论一些概念,这些概念咱们在开始学习JavaScript的时候就知道了,JavaScript是一个弱类型且动态类型的语言
,那么这些概念具体这里作了整理。以后还要重点讨论的是 JavaScript自有类型系统的问题
,以及如何借助一些优秀的技术方案,解决这些问题。函数
咱们常常用两个维度去描述一个编程语言的特性,这两个维度不要混淆,强类型并非动态类型...工具
强类型 :要求语言层面限制函数的实参类型必须与形参类型相同。弱类型 : 语言层面不会限制实参的类型。学习
下面举个例子:开发工具
// Java class Main { // 这里定义了传入的参数是int类型,那么实际的时候也应该是int类型 static void foo(int num) { System.out.printIn(num); } public static void main(Sting[] args) { // 下面的若是int类型就经过,若是不是int类型就会报错 Main.foo(100); // ok Main.foo('100'); // error "100" is a string Main.foo(Integer.parseInt("100")); // ok } } // --------------------------------------------------- // JavaScript // 传的时候没有规定是什么类型,那么实参是什么类型都不会报错 function foo(num) { console.log(num) } foo(100) // ok foo('100') // ok foo(parseInt('100')) // ok
因为这种强弱类型之分根本不是某一个权威机构的定义,因此以后的人们对制定的细节出现了不同的理解。大体也就是说强类型有更强的类型约束,而弱类型中几乎没有什么约束。
强类型语言中不容许有任何的隐式类型转换,而弱类型语言则容许任意的数据隐式类型转换。
测试
// JavaScript // js报的错误都是在代码层面,运行的时候经过逻辑判断手动抛出的,并非语法层面的类型限制 // 下面'100'是字符串,在作减法的时候进行了隐式类型转换,转换成了Number类型,最后获得的结果是50,Number类型。 > '100' - 50 50 // 下面字符串进行隐式类型转换,不是数字的成为NaN(不是数字) > Math.floor('foo') NaN // 布尔值进行隐式类型转换,转成了数字1 > Math.floor(true) 1
# python # 这里没法进行隐式类型转换,会在语法层面上报类型错误 > '100' - 50 TypeError: unsupported operand type(s) for -: 'str' and 'int' > abs('foo') TypeError: bad operand type for abs(): 'str'
都比较统一,没什么争议
静态类型 :一个变量声明时它的类型就是明确的,声明事后,类型不能修改。动态类型 :运行阶段才能够明确变量的类型,并且变量的类型随时能够改变。因此动态类型语言中的变量没有类型,变量中存放的值时有类型的。
// Java class Main { public static void main(String[] args) { // 一开始就定了num的类型是int,若是修改也只能修改为int类型,若是修改为string就会报错 int num = 100; num = 50; // ok num = '100' // error System.out.printInt(num); } } // JavaScript // 能够随意修改num的类型 var num = 100 num = 50 // ok num = '100' // ok num = true // ok console.log(num)
静态类型不能修改变量的类型,动态类型能够随时去修改变量的类型。
JavaScript是弱类型且动态类型的语言,灵活多变,能够进行 隐式转换 ,也能够进行 类型推断 ,可是缺失了类型系统的可靠性。
JavaScript
应用简单,因此并无复杂的类型系统JavaScript
是脚本语言,没有编译环节,因此设计成静态语言是没有意义的JavaScript
应用愈来愈复杂,开发周期也愈来愈长,愈来愈大的项目几百行代码已经不知足现状了,因此如今弱类型已经成为了JavaScript
的短板。const obj = {} obj.foo() // TypeError: obj.foo is not a function // 下面这个延时器,在时间到了以后才会运行,给测试带来麻烦 setTimeout(() => { obj.foo() }, 100000)
// 不明确是数字,因此结果不同 function sum (a, b) { return a + b } console.log(sum(100, 100)) // 200 console.log(sum(100, '100')) // 100100
// 定义一个字符串,对象的属性名不能是对象,会自动转换成字符串,若是不知足就会有问题 const obj = {} obj[true] = 100 obj[{name:1}] = 1 console.log(obj) // {true: 100, [object Object]: 1} console.log(obj['true']) // 100 console.log(obj["[object Object]"]) // 1
function sum (a, b) { if (typeof a !== 'number' || typeof b !== 'number') { throw new TypeError('arguments must be a number') } return a + b }
这里以后会进行内容补充
使用专门的编译器,针对特定的平台,将高级语言源代码一次性的编译成可被该平台硬件执行的机器码,并包装成该平台所能识别的可执行性程序的格式。
编译型语言一次性的编译成平台相关的机器语言
文件,运行时脱离开发环境,与特定平台相关,通常没法移植到其余平台,现有的C、C++、Objective等都属于编译型语言。
使用专门的解释器对源程序逐行解释成特定平台的机器码并当即执行。是代码在执行时才被解释器一行行动态翻译成机器语言和执行
,而不是在执行以前就完成翻译。解释型语言每次运行都须要将源代码解释称机器码并执行,只要平台提供相应的解释器,就能够运行源代码,Python、Java、
JavaScript
等属于解释型语言。