1974年,两位美国计算机科学家Liskov,Zilles提出强类型语言的概念。java
在强类型语言中,当一个对象从调用函数传递到被调用函数时,其类型必须与被调用函数中声明的类型兼容c++
function A(){
B(x)
}
function B(y){
// y能够被赋值x,程序运行良好
}
复制代码
这是一个较为宽泛的定义,并无阐述具体的规则,后人对强类型语言的定义则会更精确一些。浏览器
强类型语言:不容许改变变量的数据类型,除非进行强制类型转换。bash
以java为例函数
public class HelloWorld {
public static void main(String []args) {
int x =1;
boolean y = true;
x = y;
System.out.println(x);
}
}
复制代码
定义x为数字,y为布尔值,将y赋值给x,会报错。工具
public class HelloWorld {
public static void main(String []args) {
int x =1;
char y = 'a'
x = y;
System.out.println(x); // 97
}
}
复制代码
定义x为数字,y为字符,将y赋值给x,最终值为97,Java在这里进行了强制类型转换,将字符a的ASCll码赋值给了x,这样x的数据类型依旧是整型。性能
弱类型语言:变量能够被赋予不一样的值单元测试
仍然是刚才的例子,在浏览器中用js来运行。测试
总而言之,强类型语言对变量的类型的转换有严格的限制,除非进行强制类型转换,不一样类型的变量是不能相互赋值的,这样就能够避免一些低级错误。而弱类型语言就没有什么约束,能够很灵活地进行类型转换,但也更容易产生bug。ui
静态类型语言:在编译阶段肯定全部变量的类型。
动态类型语言:在执行阶段肯定全部变量的类型。
用一个例子来讲明:
class C {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
function add(a) {
return a.x + a.y;
}
var c1 = new C(10, 20);
var c2 = new C('hello', 'world');
console.log(add(c1)); // 30
console.log(add(c2)); // helloworld
复制代码
定义一个类C,并为它添加了两个属性x和y,而后定义了一个add函数,用来把一个实例的全部属性相加。当JS编译器看到这段代码时,它彻底不知道add函数里的参数a的类型是什么,只有执行的时候才知道。最终c1是数字相加,c2是字符串拼接。
一样的代码,用c++实现
class C {
public;
int x;
int y;
}
int add(C a) {
return a.x + a.y;
}
复制代码
在编译的时候,就知道C里面的属性x和y的类型是整型了。
从内存分配的角度来看上面的例子,c++因为一开始就定义好了属性类型是整型,因此假设x是基地址,那么y就在基地址+4的位置上。js则不一样,因为一开始不知道属性类型,因此也不知道每一个属性要占多少地址空间,因此须要额外的空间存储属性名,在程序运行时,再动态计算属性的地址偏移量。
由此看来,动态类型语言在空间占用上会有一些损耗。
总结一下二者的区别
静态类型语言 | 动态类型语言 |
---|---|
对类型检查严格 | 对类型检查宽松 |
当即发现错误 | BUG不易被发现 |
运行性能较好 | 运行性能较差 |
自文档化 | 可读性较差 |
但动态类型语言也有方法来补救这些缺点,好比,
因此虽然js是一门动态弱类型语言,但它倒是目前最流行的语言之一,就是由于它的灵活和应用场景普遍。
最后,看一下各类语言的强弱类型和动态静态类型吧。