Type safety是一个复杂的话题,目前还没有人对“类型安全”语言的定义达成一致。但通过几乎所有的定义,不,JavaScript不是类型安全的。 :-)在这个特定的例子中,JavaScript确实提供了运行时类型安全性:它实际上并没有试图调用i
并导致某种内存访问异常或类似;相反,当你的代码尝试调用它时,JavaScript引擎所做的第一件事就是检查它是否可调用,并且由于它不是,所以引发了一个保护性错误。
但类型安全的语言通过类型强制(在编译/解析阶段和代码运行时)尝试阻止或防止由于使用不正确的类型而导致的错误或不可预期的行为。 JavaScript大多不会这样做(尽管如此);一般来说,JavaScript往往会强制转变。
例如,在一个类型安全的语言,这可能会失败:
console.log("hi there" * 4);
...假设*
是不是字符串定义操作。 (我相信至少有一种语言,它会导致"hi therehi therehi therehi there"
)。
但在JavaScript中,*
没有为字符串定义的含义。但不是引起错误(在编译/解析阶段或运行时),该字符串被隐式转换为数字n,然后在表达式n * 4
中使用。在字符串"hi there"
的情况下,强制导致值NaN
(“不是数字”)而不是导致错误(然后NaN * 4
也导致NaN
)。
类型安全语言通常(虽然我不认为总是)具有类型化的变量/参数/属性和类似的功能,并且在编译/解析阶段至少进行一些类型检查,而不是在相关代码运行时进行。在这些语言中,i
应该具有与其关联的类型(例如,int i
而不是var i
),并且试图将其作为函数调用的代码在编译/解析阶段将失败,而不是在稍后以它在JavaScript中完成。另一方面,JavaScript根本没有类型化的变量/参数/属性。一个变量可以容纳一个对象,下一个容纳一个原始数字。
其中一个好处是JavaScript对鸭子打字(如果它看起来像一只鸭子,嘎嘎叫鸭子,它是一只鸭子)。举例来说,假设你有一个函数,理论上,需要一个字符串:
function capitalize(str) {
return str.charAt(0).toUpperCase() + str.substring(1);
}
在JavaScript中,下面的代码调用它:
capitalize(42);
是完全正确的,不会引起任何错误时,包含该调用的代码被编译/解析。但它将在调用代码时引发错误 —不是因为42不是字符串(它不是,但那不是重点),而是因为42没有charAt
方法。
在具有静态类型安全性的语言(例如,编译/解析阶段类型安全性)中,应该有与str
参数关联的类型信息,并且该错误将在代码编译/解析时出现。
但在JavaScript中,它不仅是快乐编译/解析代码,但它是乐意为提供任何你给它一个非字符串运行它符合这些标准:
它有一个charAt
方法返回的东西与toUpperCase
方法,和
它有一个substring
方法。
只要你给它满足这些标准的东西,不管它是否是字符串,它都可以工作。
function capitalize(str) {
return str.charAt(0).toUpperCase() + str.substring(1);
}
var thingy = {
charAt: function() {
return {
toUpperCase: function() {
return 40;
}
}
},
substring: function() {
return 2;
}
};
console.log(capitalize(thingy)); // 42
;-)
类型安全,因为在JS会自动转换一些东西,以适合你的不同类型,例如'alert('himom'+ 42)'会输出'himom42',即使“string + integer”没有数学意义。 –
那么一个整数不是一个函数,如果没有指出这个事实的错误,你预期会发生什么? –
Javascript具有动态类型安全性,换句话说,它在运行时引发一些TypeError异常。通常'类型安全语言'是一个术语,用于表示在代码执行之前进行验证。 – Jaco