JavaScript是一种无类型语言吗?

115
我发现一些人将JavaScript称为“动态、弱类型”的语言,但有些人甚至说是“无类型”?它到底是哪种类型?
9个回答

142

JavaScript无类型的:


(来源:no.gd)

甚至 Brendan Eich 也这么说。在 Twitter 上,他回复了一个链接到这个问题的帖子:

... 学术界使用“无类型”来表示“没有静态类型”...

所以问题在于有几种不同的 无类型 定义。

其中一种定义已经在上面的答案中被讨论过 - 运行时不标记值,只将每个值视为位。JavaScript 标记值,并根据这些标记具有不同的行为。因此,JavaScript 显然不属于该类别。

另一种定义来自于 编程语言理论(Brendan 所指的学术领域)。在这个领域,无类型 只是意味着 一切都属于单一类型

为什么呢?因为只有当语言可以证明类型对齐(即Curry-Howard 对应;类型是定理,程序是证明)时,语言才会生成程序。这意味着在一个无类型的语言中:

  1. 程序总是会被生成
  2. 因此类型总是匹配
  3. 因此必须只有一个类型
与静态语言相比:
  1. 可能不会生成程序
  2. 因为类型可能无法匹配
  3. 因为程序可以包含多种类型
因此,在PLT中,“未经类型化”的意思就是动态类型化,“已经类型化”的意思就是静态类型化。JavaScript在这个类别中肯定是未经类型化的。 参见:

7
当然,“没有静态类型”和“没有类型声明”也并不相同。 - Andreas Rossberg
Crockford 坚持使用 K&R 大括号风格。我是说,真的吗?这是什么鬼。不过,除此之外,我认为他在编程方面有很多有趣的观点。哦,对了,我已经知道关于分号自动插入的 唯一 用例问题了。 - Almo
3
编程语言理论是正确的。巨大的截屏是错误的。 - Alex W
2
我很高兴看到这个回答提到了哈珀的博客文章,但如果PLT社区能够放弃“untyped”而使用“unityped”,那将会更好。 “untyped”的定义是指“只是比特”,这是有意义的。将“untyped”用来描述一种语言,其形式规范使用单词“类型”,并且说它有七种类型(Undefined、Null、Number、String、Boolean、Symbol和Object),这真的很令人困惑。大多数人不想区分这种类型观念和PLT定义之间的差异。 - Ray Toal
5
你对于弱类型语言的 1. 2. 3. 并不适用于 JavaScript。JavaScript 不只有一种类型,大约有四到五种类型。那么这如何证明 JavaScript 是弱类型语言呢? - Don Cheadle
显示剩余6条评论

92
strong/weakcan可以理解为编译器(如果适用)如何处理类型的关系。
  • Weakly typed means the compiler, if applicable, doesn't enforce correct typing. Without implicit compiler interjection, the instruction will error during run-time.

    "12345" * 1 === 12345  // string * number => number
    

    Strongly typed means there is a compiler, and it wants you an explicit cast from string to integer.

    (int) "12345" * 1 === 12345
    

    In either case, some compiler's features can implicitly alter the instruction during compile-time to do conversions for you, if it can determine that is the right thing to do.

    Thus far, JavaScript can be categorized as Not-Strongly-Typed. That either means it's weakly-typed or un-typed.

动态/静态可以被理解为语言指令如何操作类型。
  • Dynamically typed means the value's type is enforced, but the variable simply represents any value of any type.

    x = 12345;    // number
    x = "string"; // string
    x = { key: "value" }; // object
    y = 123 + x; // error or implicit conversion must take place.
    

    Statically typed means the variable type is strongly enforced, and the value type is less-so enforced.

    int x = 12345; // binds x to the type int
    x = "string";  // too late, x is an integer - error
    string y = 123; // error or implicit conversion must take place.
    

    Thus far, JavaScript can be categorized as Not-Statically-Typed. Also, it appears to be Dynamically Typed, if typed at all. So we need to see what Typing means.

Typed 意味着该语言区分不同的类型,例如 字符串数字布尔值对象数组nullundefined 等等。此外,每个操作都与特定的类型绑定。因此,您不能将一个 整数 除以一个 字符串

    2 / "blah"  // produces NaN
Untyped 意味着将 integer 除以 string 的操作会将 string 的前四个字节视为 integer。这是因为 Untyped 操作直接在位上进行,没有类型可观察。结果将是非常意外的:
    2 / "blah"  // will be treated as  2 / 1500275048

由于JavaScript的行为是按照类型定义的,因此它必须是动态类型和弱类型。如果有人声称JavaScript是无类型的,那只是学术理论,而不是实际应用。


1
但我认为最后一句话存在矛盾。在JavaScript中,整数字符串除法的结果对于任何整数或字符串的值都是明确定义的。只是它不太有用! - Deniz Dogan
如果您有更好的定义/描述,请随意进行编辑。这就是为什么我将其设置为社区Wiki的原因。 - Gumbo
@skurpur:你完全颠倒了动态类型和弱类型的含义 - 已经更正。 - Rene Saarsoo
哦,抱歉,你在我编辑的同时也进行了编辑,我覆盖了你的更改。 - Rene Saarsoo
3
-1. 你需要阅读这篇文章 - missingfaktor
变量的类型与值的强制转换无关,而与变量类型的声明有关。Javascript根本没有这样的结构,这就是为什么很少有Javascript程序员理解这个概念,也是为什么他们中的许多人将变量类型定义错误地看作是与比较或强制转换变量类型有关的东西。在JS中,你根本不能声明String a = "blah";或者var a:String = 'blah';(即有类型的变量)。这就是为什么它是无类型的。 - Jimbo Jonny

50
JavaScript是弱类型的。它绝对不是"未经类型化",但其弱类型的特性允许进行很多隐式转换。
请记住,JavaScript也是动态类型的。这种类型的方法允许所谓的"鸭子类型"
相比之下,JavaScript既不是强类型也不是静态类型。有时理解某些东西不是什么可以帮助你更好地看到它是什么。

2
你需要阅读这篇文章,它与编程语言的类型系统有关。 - missingfaktor
5
这个回答比得票最高的回答好得多,而且更准确。 - Alex W
3
@JimboJonny说的不正确。除非在Assembly开发人员的存在下,否则声明每种语言都是静态类型语言并不完全正确。动态类型语言指的是仅对比特操作进行直接操作,而考虑一下Javascript具有toString()和parseInt()方法,这就比这更加具有类型特征了。 - Suamere
2
@Suamere - 来自W3C代表Charlie Kindel的说法:“VB、VBScript和JavaScript是无类型的” - Jimbo Jonny
3
如果你相信某些人所声称的学术界人士故意使用“untyped”一词来表示“动态类型”,那么根据所有证据,JavaScript是无类型的。但如果你知道“untyped”被错误地用来表示真正的“动态类型”语言,那么就简单地称这些语言为“动态类型”。http://tinyurl.com/czhcv54 - Suamere
显示剩余6条评论

9
这里困惑了很多程序员的问题是,像这样的定义在某个地方没有标准化。术语“非类型编程语言”是模糊的。那是指一个没有数据类型的语言还是一个λ演算的无类型变体语言?
JavaScript / ECMAScript 有一种类型系统,所有函数的域都将接受任何参考规范类型。这意味着 JavaScript 实际上只有一种数据类型。这是实现更重要的问题,对于极其高级的 JavaScript 程序员来说更为重要。普通的 JavaScript 程序员只关心由 ECMAScript 指定的抽象语言数据类型。
在日常程序员的情况下,不是研究人员或理论计算机科学家,术语“非类型”是一个用词不当,因为大多数人并不使用λ演算。因此,这个术语使大众感到困惑,并似乎宣称 JavaScript 没有任何数据类型,这显然是不正确的。任何使用 typeof 的人都知道 JavaScript 有自己的语言数据类型:
var test = "this is text";
typeof(test);

yield(产出)

"字符串"

ECMAScript 定义了以下八种语言类型:Undefined、Null、Boolean、String、Symbol、Number、BigInt 和 Object。

更准确地说,JavaScript 的设计应该被称为隐式类型、动态类型或者弱类型/松散类型(或它们的某些组合),因为在某些情况下 JavaScript 使用类型转换来使类型变得隐式,因此你不必显式地指定变量的类型。它属于弱类型,因为与一些区分浮点数和整数等的语言不同,它只使用一个number类型来涵盖所有数字,并利用前面提到的类型转换【ECMAScript 规范第9节】,这与强类型语言形成了鲜明的对比,后者将具有非常特定的数据类型(例如,你需要指定intfloat)。

静态类型语言和动态类型语言的定义没有标准化,但是在计算机开始演变时,字节大小也没有标准化。静态和动态类型通常指某些语言特性的存在。其中之一是运行时类型检查,或者所谓的动态类型检查。如果你使用过JavaScript,你已经知道它肯定会等到运行时才检查类型,这就是为什么在执行代码期间会出现TypeError异常的原因。此处有示例 我认为得票最高的答案混淆了JavaScript函数的多态与接受任何东西的函数(与Lambda Calculus的未类型化变体一样), 这是一个关联谬误

这不是一个错误的名称,但上下文很重要,请参见https://dev59.com/XWox5IYBdhLWcg3whUkV#9166519。 - Andreas Rossberg
1
@AndreasRossberg,这绝对是一个错误的名称。在您“毫不掩饰地自我推销的链接”中所提到的是类型系统。该术语之所以是错误的名称是因为它是模糊的。当程序员听到“未类型化语言”时,他们大多数人会想到“数据类型”,而不是“类型系统”。我认为Konrad Rudoph的评论真正阐明了这一点。 - Alex W
不确定为什么你认为引用我之前的回答而不是在这里重复它是“无耻”的。此外,我明确表示上下文很重要。与K. Rudolph的抱怨相反,在文献中有完全一致且广泛接受的“类型系统”定义,并且我引用了其中一个。当然,你可以在你的上下文中发现它们令人困惑,但这并不意味着它们是“错误的名称”。 - Andreas Rossberg
1
@AndreasRossberg 这里上下文非常重要。得票最高的回答说“untyped = 没有类型声明”,这显然是错误的。我想说的是,在这种情况下,这是一个误用。没有人在这里提到 λ演算,这样做有点自命不凡。 - Alex W

9

根据作者的观点,JavaScript 也被归类为 动态类型。维基百科指出,动态类型语言是在运行时进行类型检查而不是在编译器中进行的,而弱类型则是指能够在代码中随意更改类型的能力。因此,它既是动态类型又是弱类型。


1

请记住,JavaScript 允许您询问 typeof(your_variable) 是什么,并比较类型:5==="5" 返回 false。因此,我认为你不能称它为无类型。

它是动态和(估计为)弱类型的。您可能想知道它使用鸭子类型(请参见安德鲁的链接),并通过 原型 而不是类和继承来提供 OOP。


变量的类型与值的强制转换无关,而与变量类型的声明有关。Javascript根本没有这样的结构,这就是为什么很少有Javascript程序员理解这个概念,也是为什么他们中的许多人将变量类型定义错误地看作是与比较或强制转换变量类型有关的东西。在JS中,你根本不能声明String a = "blah";或者var a:String = 'blah';(即有类型的变量)。这就是为什么它是无类型的。 - Jimbo Jonny

0

虽然它是有类型的(你可以问“typeof someVar”并了解其具体类型),但它非常弱。

假设:

  var a = "5";

你可能会说a是一个字符串。然而,如果你接着写:

  var b = a + 10;

b是一个等于15的整数,所以a的行为就像一个整数一样。当然,你也可以这样写:

  var c = a + "Hello World";

而c将等于"5Hello World",所以a再次像字符串一样运作。


  1. 转换值 != 类型化变量
  2. 它不是弱的,它不存在。你不能在JavaScript中为变量指定类型。
- Jimbo Jonny
好奇为什么这个答案收到了两个踩。我在弱类型定义中找到的确切说法是:一个值的类型是根据它的使用方式来确定的。 - aioobe
1
这是否准确?我得到了 b 等于 510:https://ideone.com/BRcSW7 - aioobe
b等于510,因为类型强制转换影响了数字10。如果你把一个数字和一个字符串相加,结果就是一个字符串。这仍然说明了JS为什么是一种弱类型语言,但是...最终结果仍然是“5Hello World”,因为a在内存中仍然是'5'。他的答案只对了一半lol。 - Robert O'Toole

0

我认为 JavaScript 是强类型和动态类型的。

但这取决于一堆术语,这些术语似乎最好是松散定义的,因此如果您接受以下定义,上面的说法才是正确的...

强/弱

  • "强"类型防止针对其他类型的数据执行操作。例如,在不是数组对象的情况下尝试写入数组的第 N 个元素。内存安全需要强类型。
  • "弱"与"强"相反。

静态/动态

  • "静态"类型在程序执行之前(在编译/转换时)检查类型。这需要将类型信息编码到语言的语法中。
  • "动态"与"静态"相反。

JavaScript不会让您破坏内存(因此"strong"),但会在运行时执行所有检查和类型转换/强制转换(因此"dynamic")。


我发现将“强类型 vs 弱类型”与“静态类型 vs 动态类型”视为正交的概念是有帮助的。有些语言是强类型和静态类型(例如没有unsafe上下文的C#),有些是强类型和动态类型(大多数“脚本”语言似乎属于这一类),还有一些是弱类型和静态类型(C/C++)。

不确定什么是弱类型和动态类型...也许是汇编语言吧 :)


在我看来,“内存安全”是一个更好的说法,可以用于这个答案中,而不是使用“强”这个词。 - Peter O.

-1

另一个有趣的松散类型 JS 的例子:

console.log(typeof(typeof(5)))

结果是字符串。为什么?因为初始 typeof 的结果是 'integer',它本身就是一个字符串。我会认为在强类型语言中这种类型的转换不会存在。也许我错了,但那是我开始理解 JS 有多疯狂的第一个例子,哈哈。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接