资讯专栏INFORMATION COLUMN

JavaScript 程序员可以从C++中学到什么

不知名网友 / 2199人阅读

摘要:特别是所谓的不需要的引用可能会导致内存泄漏,这意味着程序占用的内存比实际需要的多,从而降低了内存的效率。但是如果我们能够意识到内存泄漏的风险,就可以采取措施将其删除。意外的使用全局变量是导致内存泄漏的一个常见原因。

作者:Bret Cameron
翻译:疯狂的技术宅
原文:https://medium.com/@bretcamer...

本文首发微信公众号:前端先锋
欢迎关注,每天都给你推送新鲜的前端技术文章

如何通过了解类型、内存以及低级语言使你成为更好的程序员

时间的结束?图片来自 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 将根据一组规则进行猜测。有时这很管用,它可以帮助我们快速简洁地编写代码。但有时候可能是引发混乱的原因。

实际上即使这种行为从根本上来讲是可预测的,但某些自动推测也不那么直观,并且在很多大型项目的代码库中,很容易看到类型强制转换导致了意外错误的发生。例如以下是使用组合字符串和数字的进行运算的一些演示:

"10" - 4
// 6

"10" + 4
// "104"

"20" - "5"
// 15

"20" + "5"
// 205

"20" + + "5"
// 205

"foo" + "bar"
// "foobar"

"foo" + + "bar"
// "fooNaN"

"6" - 3 + 3
// 6

"6" + 3 - 3
// 60

在这些例子中, + 运算符造成了大量的混乱,它可以强制把字符串转为数字,也可以作为连接运算符组合两个或多个字符串。

最后一个例子可能是最令人困惑的。在 "6" + 3 — 3 中,如果首先处理 3 — 3 ,然后再进行字符串连接,"6" + 0 会返回一个字符串,但是在这里返回的结果居然是一个数字!

虽然类型强制转换可以帮助开发人员更快速、简洁地编写代码,但是它使初学者思考得更少,从而也就不清楚为什么这样的转换系统可能会导致错误,特别是在更大、更复杂的代码库中。上面的结果对于经验丰富的 JavaScript 程序来说可能是完全合理的,但它们并不直观!

考虑到 JavaScript 类型强制系统的优点和缺点,现在让我们看看 C++ 是如何处理数据类型的。

C++ 中的类型和内存管理

C++ 之类的低级语言没有这种潜在缺陷,因为必须在定义时声明数据类型。虽然 JavaScript 也有三个关键字  varletconst  用于声明新变量,但在C ++中每个数据类型都有自己的关键字。

例如 C++ 中的 7 种基本数据类型是整型、浮点型、双精度浮点型,字符型,宽字符型,布尔型和无类型。用于定义它们的关键字分别是 intfloatdoubleboolcharwchar_tvoid

下面的代码段包含了每种类型的示例声明,并添加了注释:

#include 
#include 
using namespace std;

int main()
{
 
  // BOOLEANS
  bool isChecked = true;
  
  // INTEGERS
  int age = 24;

  // FLOATS
  // In general, a float has 7 decimal digits of precision, while a double has 15
  float pi7 = 3.1415926;
  double pi15 = 3.141592653589793;
  
  // CHARACTERS
  // Regular characters can contain only values stored in the ISO Latin tables
  // Wide characters, however, can contain unicode values
  char englishGreeting[6] = {"H", "e", "l", "l", "o", ""};
  wchar_t mandarinGreeting[7] = { "n", "ǐ", " ", "h", "ǎ", "o", "" };
  
  // STRINGS
  // In C++, string is not a data type (as it is in JavaScript and many other languages) 
  // It is a class, and so we must write #include  at the top of the document
  string greeting = "Hello";
  
  // VOID
  // A common use of void is to define functions which don"t return anything
  void printMessage() {
    cout << "Hello, world!";
  };
  
  return 0;
}

与 JavaScript 不同,C++ 为开发人员提供了大量内存管理的方法。在 C++ 中,每声明一个变量时,我们也会决定要保留多少内存。例如,普通的 char 通常只包含8位(1字节),这就将其用途限制为 ISO Latin 表的255个字符。相比之下,wchar_t 包含16或32位,虽然占用了更多内存,但允许我们能够访问更多种类的 Unicode 字符。

在整型中可以找到最多的种类,其中基本的 int 关键字可以与关键字 shortlonglong long 以及 “signedness” 关键字 signedunsigned 结合使用。 。

基本的 int 类型的取值范围是系统体系建议的自然范围。在 64 位操作系统上通常是 32 位。这就意味着这样的一个有符号的变量的取值范围在 -2,147,483,648 和 2,147,483,647 之间,而无符号变量的取值范围是 0 到 4,294,967,295 之间。

如果你能够确认自己的变量取值范围比较小,可以使用 short int 来节省内存。或者如果你正在处理非常大的整数,你可以使用 unsigned long long int 来处理 64 位的数字,其取值上限为 2^64 - 1

为什么内存至关重要:一个关于时间溢出的用例

使用 64 位变量(例如 long long int)可以让计算机表示未来约 2.92 亿年的日期。这似乎是没什么必要的,但它实际上解决了一个非常实际的问题。

按照惯例,计算中的大多数日期都是用 Unix 时间来表示的,该时间的起始日期是 1970 年 1 月 1 日午夜,精确到秒。如果将 Unix 时间存储在有符号的 32 位变量中,可记录的最大值为 2,147,483,647。虽然看起来很大,但考虑到它每一秒都在增长,实际上 20 亿并不能让我们用得太久。

实际上 32 位系统上记录的日期将在 2038 年 1 月 19 日 UTC(恰好是 03:14:07 )达到最大值。当这种情况发生时,日期将会变为负的 2,147,483,647,这个时间是 1901 年 12 月 13 日。它被称为 2038 问题,并且它导致了许多标题的出现,例如“所有计算机将在 2038 年完蛋” —— 由英国小报 Metro 提供。

这个令人震惊的标题可能并非事实,但是当 2038 年到来时,这个问题可能会导致 32 位操作系统甚至是整个旧版本的编程语言出现问题。我第一次遇到这个问题时正在用 PHP,在 5.2 版本之前没有内置的方式能够记录超过 2038 年的日期。(JavaScript 使用了 64 位系统来处理日期,所以我们 JavaScript 程序员不用担心这个)

2038 问题证明了我们自己管理内存的潜在用处。在需要较小取值范围的地方可以节省内存。在需要更大取值范围的场合,可以确保我们的系统能够拥有足够的内存。

JavaScript 中的内存管理
“JavaScript 在创建对象时自动分配内存,并在不再使用时释放它(垃圾回收)。这种自动化处理可能会引起混乱:它可能会给程序员带来错误的暗示,即他们不需要担心内存管理问题。“ ——  MDN

JavaScript被称为“自动垃圾回收”语言。它用 mark-and-sweep 算法来检查哪些内存是活动的,哪些是“垃圾”。然后收集器可以释放“垃圾”,将未使用的内存还给操作系统。

自动垃圾回收是高级语言的一个特征,它有助于释放内存——不需要通过程序员的明确指示就可以告诉它不再需要。有关 JavaScript 中垃圾回收机制的信息,请查看这篇文章和 MDN’s page on Memory Management。

垃圾回收是一个强大的自动内存管理系统,但它并非万无一失。特别是所谓的“不需要的引用”可能会导致内存泄漏,这意味着程序占用的内存比实际需要的多,从而降低了内存的效率。但是如果我们能够意识到内存泄漏的风险,就可以采取措施将其删除。

意外的使用全局变量是导致内存泄漏的一个常见原因。当我们在 JavaScript 代码中没有用关键字 varletconst 定义变量时,那么它会自动被认为是一个全局变量。除非已定义了 foo,否则表达式 foo =“bar” 相当于 window.foo = "bar"

像 ESLint 这样的 linting 工具可以帮助你找出这样的错误,但是 JavaScript 内置的严格模式也可以将它们标记为错误,从而防止意外使用全局变量。要激活严格模式,只需在脚本或函数的开头加入"use strict";。有关从代码中去除内存泄漏风险的更多方法,请参阅这篇文章。

JavaScript 中的类型

还有一些方法可以指定变量类型并在 JavaScript 中创建自己的类型,这种方式让人想到低级语言。最流行和最全面的解决方案是 TypeScript,它是 JavaScript 的语法超集,为语言添加了静态类型选项。

在 TypeScript 上有很多不错的资源,足以说明它是能确保你代码可扩展性而且没有错误的好方法,它可以帮助我们避免本文在前面关于“强制类型”那一节中看到的那种不直观的结果。 TypeScript 的文件扩展名是 .ts,还有一个等效的 .jsx.tsx。对初学者来说最好的一篇文章是5分钟入门 TypeScript 。

值得注意的是,还有一些针对不同 JavaScript 技术的类型注释解决方案。例如你可以将官方的 PropTypes node module 添加到你的 React 项目中。这使你可以记录传递给组件的 props 的预期数据类型以及设置默认值。特别是当与像 ESLint 这样的 linter 结合使用时,PropTypes 是基于 React 的设置的强大补充。

结论

总的来说,我希望本文有助于阐明 C++ 这样的低级语言和 JavaScript 这类高级语言之间的一些差异。

我也希望它能够为你提供一种工具,以 TypeScript 或 PropTypes 的形式将 C++ 中的一些好处带入 JavaScript,并可以影响和改进 JavaScript 中的内存管理。

如果你对 C++ 有深入的理解,并且想要了解更多关于 JavaScript 的实现方式,最好的去处可能是官方 V8 网站或者官方 Git repo。Happy coding!

本文首发微信公众号:前端先锋 欢迎扫描二维码关注公众号,每天都给你推送新鲜的前端技术文章

欢迎继续阅读本专栏其它高赞文章:

12个令人惊叹的CSS实验项目

必须要会的 50 个React 面试题

世界顶级公司的前端面试都问些什么

11 个最好的 JavaScript 动态效果库

CSS Flexbox 可视化手册

从设计者的角度看 React

过节很无聊?还是用 JavaScript 写一个脑力小游戏吧!

CSS粘性定位是怎样工作的

一步步教你用HTML5 SVG实现动画效果

程序员30岁前月薪达不到30K,该何去何从

14个最好的 JavaScript 数据可视化库

8 个给前端的顶级 VS Code 扩展插件

Node.js 多线程完全指南

把HTML转成PDF的4个方案及实现

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/103826.html

相关文章

  • 只看不敲,神也学不好C---------计算机经典书籍经验分享

    摘要:学单片机多去官网上查资料,下载手册,像我入门的单片机经常去官网,还有学的系列板子,公司的官网的官方例程给的很详细,在英文视角阅读对你大有益处。 目录 1.C语言经典 2.单片机系列 3.Python方面 4.嵌入式LWip协议 5.Android 6.C++经典书籍 7.Linux开发 ...

    FleyX 评论0 收藏0
  • 儿童节 | 让你在“我的世界”,“添码”行空

    摘要:目前,京东云助力教育版落地,可提供等编程语言的学习。而这几种语言也是专门针对适龄儿童的教育而选择的,便于学生通过积木式的可视化过程进行学习。点击京东云可了解更多信息。让每一个小孩,都可以在成长过程中轻松快乐,添码行空。 showImg(https://segmentfault.com/img/bVbtxeg?w=1264&h=216); showImg(https://segmentf...

    chengjianhua 评论0 收藏0
  • 985非科班本科毕业,当了两年CRUD序员后,我躺平了

    摘要:一次为了蹭讲座票的缘故集齐讲座票是毕业要求之一去听了一场机器学习汇报的讲座,感觉预测模型很有意思,回来以后就赶紧在网上寻找相关的内容,语言便进入了我的视野。   六...

    villainhr 评论0 收藏0
  • 来点CoffeeScript吗?

    摘要:一般来说,可以缩短大约的代码长度。这就避免了意外创建全局变量。使用表示,不推荐的和将不能使用。因此,使用将是有效的解决方法之一。 简单易懂的介绍 CoffeeScript是什么? 首先,它是一门小巧的编程语言。有一本关于CoffeeScript的指南,写作The Little Book on CoffeeScript: showImg(https://segmentfault.com/...

    KavenFan 评论0 收藏0

发表评论

0条评论

不知名网友

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<