每日前端夜话0x5A
每日前端夜话,陪你聊前端。
每天晚上18:00准时推送。
正文共:3380 字
预计阅读时间:10 分钟
作者:Bret Cameron
翻译:疯狂的技术宅
如何通过了解类型、内存以及低级语言使你成为更好的程序员
时间的结束?图片来自 Jens Kreuter 由Bret Cameron修改。
像许多开发新手一样,JavaScript 是我学的第一门语言。它是一种 Web 前端编程语言 —— 感谢Node.js —— 它同时也是一种流行的后端工具。
我也相信,作为一种“更高级”的语言,JavaScript 是初学者的绝佳选择。你可以在任何 Web 浏览器上运行它,并且由于具有原型继承和动态类型等功能,学习者在编写和执行第一段代码之前克服的障碍更少。
但是 JavaScript 让初学者更容易上手的因素也让它难以被掌握。它能以看上去不直观的方式运行,并且当涉及到更多不透明的功能时,许多程序员更依赖于试错法,例如隐式类型强制转换或 this
关键字。知道这些功能比理解它们要容易得多。
“Any fool can know. The point is to understand.” — Albert Einstein
“傻瓜也能够知道很多东西,重要的是它搞明白。” —— 阿尔伯特·爱因斯坦
因此要成为更高级的 JavaScript 开发人员,试着更深入地了解幕后发生的事情是有很大帮助的。归根结底,最精彩的地方是 V8 JavaScript 引擎:它是使用最广泛的 JavaScript 编译器(Google Chrome、Node.js等的基础之一),它是开源的,因此你可以准确地看到 JavaScript 是怎样在 C 中执行的。
但是本文不是 V8 的指南。相反,它是有关像 C 这样的低级语言如何帮助我们提高对 JavaScript 等高级语言的理解的一篇文章。C 不仅可以帮助我们理解底层的编译器代码,而且通过研究 C 程序员必须要做而 JavaScript 程序员不必做的事,可以更好地了解在 JavaScript 中提升效率的地方,以及为什么有时会引发问题。
特别是我们将会研究 C 中的数据类型和内存管理,以及这些知识如何帮助我们避免类型错误,并防止 JavaScript 中的内存泄漏。还会研究内存管理与时间溢出之间的关系。
JavaScript 中强制类型
在进入 C 之前,先让我们看看 JavaScript 是如何处理数据类型以及“类型强制”系统的一些陷阱的。
JavaScript 使用类型强制转化自动将一种数据类型转换为另外一种:字符串转为数字、数字转为字符串、数字或字符串转为布尔值等等。换句话说,如果你没有明确指定所需的类型,JavaScript 将根据一组规则进行猜测。有时这很管用,它可以帮助我们快速简洁地编写代码。但有时候可能是引发混乱的原因。
实际上即使这种行为从根本上来讲是可预测的,但某些自动推测也不那么直观,并且在很多大型项目的代码库中,很容易看到类型强制转换导致了意外错误的发生。例如以下是使用组合字符串和数字的进行运算的一些演示:
代码语言:javascript复制 1"10" - 4
2// 6
3
4"10" 4
5// "104"
6
7"20" - "5"
8// 15
9
10"20" "5"
11// 205
12
13"20" "5"
14// 205
15
16"foo" "bar"
17// "foobar"
18
19"foo" "bar"
20// "fooNaN"
21
22"6" - 3 3
23// 6
24
25"6" 3 - 3
26// 60
在这些例子中,
运算符造成了大量的混乱,它可以强制把字符串转为数字,也可以作为连接运算符组合两个或多个字符串。
最后一个例子可能是最令人困惑的。在 "6" 3 — 3
中,首先处理 3 — 3
,然后再进行字符串连接。但是 "6" 0
通常会返回一个字符串,在这这里返回的结果居然是一个数字!
虽然类型强制转换可以帮助开发人员更快速、简洁地编写代码,但是它使初学者思考得更少,从而也就不清楚为什么这样的转换系统可能会导致错误,特别是在更大、更复杂的代码库中。上面的结果对于经验丰富的 JavaScript 程序来说可能是完全合理的,但它们并不直观!
考虑到 JavaScript 类型强制系统的优点和缺点,现在让我们看看 C 是如何处理数据类型的。
C 中的类型和内存管理
C 之类的低级语言没有这种潜在缺陷,因为必须在定义时声明数据类型。虽然 JavaScript 也有三个关键字 var
、 let
和 const
用于声明新变量,但在C 中每个数据类型都有自己的关键字。
例如 C 中的 7 种基本数据类型是整型、浮点型、双精度浮点型,字符型,宽字符型,布尔型和无类型。用于定义它们的关键字分别是 int
、float
、double
、bool
、char
、wchar_t
和 void
。
下面的代码段包含了每种类型的示例声明,并添加了注释:
代码语言:javascript复制 1#include <iostream>
2#include <string>
3using namespace std;
4
5int main()
6{
7
8 // BOOLEANS
9 bool isChecked = true;
10
11 // INTEGERS
12 int age = 24;
13
14 // FLOATS
15 // In general, a float has 7 decimal digits of precision, while a double has 15
16 float pi7 = 3.1415926;
17 double pi15 = 3.141592653589793;
18
19 // CHARACTERS
20 // Regular characters can contain only values stored in the ISO Latin tables
21 // Wide characters, however, can contain unicode values
22 char englishGreeting[6] = {'H', 'e', 'l', 'l', 'o', '