Type safety is a complex topic and there's no one agreed definition of what exactly a "type-safe" language is.
(类型安全是一个复杂的主题,对于“类型安全”语言的确切定义尚无统一的定义。)
But by almost any definition of it, no, JavaScript is not type-safe.(但是根据几乎所有的定义,不,JavaScript不是类型安全的。)
:-) In that particular example, though, JavaScript did provide runtime type safety: It didn't actually try to call i
and cause some kind of memory access exception or similar;(:-)但是,在该特定示例中,JavaScript确实提供了运行时类型安全性:它实际上并未尝试调用i
并导致某种内存访问异常或类似情况;)
instead, when your code tried to call it, the first thing the JavaScript engine did was check to see if it was callable and, since it isn't, it raised a protective error.(相反,当您的代码尝试调用它时,JavaScript引擎所做的第一件事是检查它是否可调用,并且由于不是,所以引发了保护性错误。)
But a type-safe language tries to discourage or prevent errors or undesireable behavior due to using an incorrect type, through type enforcement (both at the compilation/parsing stage and when the code runs).
(但是类型安全的语言会通过类型强制(在编译/解析阶段和代码运行时)尝试阻止或防止由于使用错误的类型而导致的错误或不良行为。)
JavaScript mostly doesn't do that (the above notwithstanding);(JavaScript大多不会这样做(尽管有上述情况);)
in general, JavaScript tends to coerce instead.(通常,JavaScript倾向于强制使用。)
For instance, in a type-safe language, this would probably fail:
(例如,使用类型安全的语言,这可能会失败:)
console.log("hi there" * 4);
...assuming *
isn't a defined operator for strings.
(...假设*
不是字符串的已定义运算符。)
(I believe there's at least one language where it is and that would result in "hi therehi therehi therehi there"
).((我相信那里至少有一种语言,并且会导致"hi therehi therehi therehi there"
)。)
But in JavaScript, *
doesn't have a defined meaning for strings.
(但是在JavaScript中, *
没有定义字符串的含义。)
But rather than causing an error (at the compilation/parsing stage or when run), the string is implicitly converted to a number n , and then used in the expression n * 4
.(但是,不会导致错误(在编译/解析阶段或运行时),而是将字符串隐式转换为数字n ,然后在表达式n * 4
。)
In the case of the string "hi there"
, the coercion results in the value NaN
("not a number") rather than causing an error (and then NaN * 4
also results in NaN
).(在字符串"hi there"
的情况下,强制导致值NaN
(“非数字”)而不是导致错误(然后NaN * 4
也导致NaN
)。)
Type-safe languages also typically (though I don't think always) have typed variables/parameters/properties and similar and do at least some type checking at compilation/parsing stage rather than when the relevant code runs.
(类型安全的语言通常(尽管我不总是认为)具有类型化变量/参数/属性等,并且至少在编译/解析阶段而不是在相关代码运行时进行某种类型检查。)
In those languages, i
would have had a type associated with it (eg, int i
rather than var i
), and the code trying to call it as a function would have failed at the compilation/parsing stage, rather than later when it was run as it does in JavaScript.(在那些语言中, i
本来会具有与之关联的类型(例如, int i
而不是var i
),并且试图将其作为函数调用的代码在编译/解析阶段会失败,而不是在之后的版本中失败。像在JavaScript中一样运行。)
JavaScript, on the other hand, doesn't have typed variables/parameters/properties at all.(另一方面,JavaScript根本没有类型化的变量/参数/属性。)
A variable can hold an object one moment and a primitive number the next.(变量可以保留一个对象,而下一刻可以保留一个原始数。)
One of the benefits of that is that JavaScript is friendly to duck-typing (if it looks like a duck and quacks like a duck, it's a duck).
(这样做的好处之一是JavaScript易于进行鸭类输入 (如果它看起来像鸭子,而象鸭子一样嘎嘎叫,那就是鸭子)。)
For instance, suppose you have a function that, notionally, requires a string:(例如,假设您有一个函数,从概念上讲,它需要一个字符串:)
function capitalize(str) {
return str.charAt(0).toUpperCase() + str.substring(1);
}
In JavaScript, the following code calling it:
(在JavaScript中,以下代码对其进行调用:)
capitalize(42);
is perfectly correct and will not raise any error when the code containing that call is compiled/parsed.
(是完全正确的,并且在编译/解析包含该调用的代码时不会引发任何错误。)
But it will raise an error when the code is called — not because 42 isn't a string (it isn't, but that's not the point), but because 42 doesn't have a charAt
method.(但这会在调用代码时引发错误-不是因为42不是字符串(不是,但这不是重点),而是因为42没有charAt
方法。)
In language with static type safety (eg, compilation/parsing stage type safety), there'd be type information associated with the str
argument and the error would be when the code was compiled/parsed.
(在具有静态类型安全性的语言(例如,编译/解析阶段类型安全性)中,将存在与str
参数关联的类型信息,并且错误将是在编译/解析代码时出现的。)
But in JavaScript, not only is it happy to compile/parse that code, but it's happy to run it on a non-string provided whatever you give it meets these criteria:
(但是在JavaScript中,不仅很高兴编译/解析该代码,而且很高兴在非字符串上运行它,只要您提供的满足以下条件的代码即可:)
It has a charAt
method that returns something with a toUpperCase
method, and
(它具有一个charAt
方法,该方法使用toUpperCase
方法返回某些内容,并且)
It has a substring
method.
(它具有substring
方法。)
As long as you give it something meeting those criteria, whether that thing is a string or not, it'll work.
(只要您给它提供符合这些条件的东西,无论该东西是否是字符串,它都将起作用。)
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
;-)
(;-))