摘要:特別是所謂的不需要的引用可能會(huì)導(dǎo)致內(nèi)存泄漏,這意味著程序占用的內(nèi)存比實(shí)際需要的多,從而降低了內(nèi)存的效率。但是如果我們能夠意識(shí)到內(nèi)存泄漏的風(fēng)險(xiǎn),就可以采取措施將其刪除。意外的使用全局變量是導(dǎo)致內(nèi)存泄漏的一個(gè)常見原因。
作者:Bret Cameron
翻譯:瘋狂的技術(shù)宅
原文:https://medium.com/@bretcamer...
本文首發(fā)微信公眾號(hào):前端先鋒
歡迎關(guān)注,每天都給你推送新鮮的前端技術(shù)文章
如何通過了解類型、內(nèi)存以及低級(jí)語言使你成為更好的程序員
時(shí)間的結(jié)束?圖片來自 Jens Kreuter,由Bret Cameron修改。
像許多開發(fā)新手一樣,JavaScript 是我學(xué)的第一門語言。它是一種 Web 前端編程語言 —— 感謝Node.js —— 它同時(shí)也是一種流行的后端工具。
我也相信,作為一種“更高級(jí)”的語言,JavaScript 是初學(xué)者的絕佳選擇。你可以在任何 Web 瀏覽器上運(yùn)行它,并且由于具有原型繼承和動(dòng)態(tài)類型等功能,學(xué)習(xí)者在編寫和執(zhí)行第一段代碼之前克服的障礙更少。
但是 JavaScript 讓初學(xué)者更容易上手的因素也讓它難以被掌握。它能以看上去不直觀的方式運(yùn)行,并且當(dāng)涉及到更多不透明的功能時(shí),許多程序員更依賴于試錯(cuò)法,例如隱式類型強(qiáng)制轉(zhuǎn)換或 this 關(guān)鍵字。 知道這些功能比理解它們要容易得多。
“Any fool can know. The point is to understand.”?——?Albert Einstein
因此要成為更高級(jí)的 JavaScript 開發(fā)人員,試著更深入地了解幕后發(fā)生的事情是有很大幫助的。歸根結(jié)底,最精彩的地方是 V8 JavaScript 引擎:它是使用最廣泛的 JavaScript 編譯器(Google Chrome、Node.js等的基礎(chǔ)之一),它是開源的,因此你可以準(zhǔn)確地看到 JavaScript 是怎樣在 C ++ 中執(zhí)行的。
但是本文不是 V8 的指南。相反,它是有關(guān)像 C++ 這樣的低級(jí)語言如何幫助我們提高對(duì) JavaScript 等高級(jí)語言的理解的一篇文章。 C++ 不僅可以幫助我們理解底層的編譯器代碼,而且通過研究 C++ 程序員必須要做而 JavaScript 程序員不必做的事,可以更好地了解在 JavaScript 中提升效率的地方,以及為什么有時(shí)會(huì)引發(fā)問題。
特別是我們將會(huì)研究 C++ 中的數(shù)據(jù)類型和內(nèi)存管理,以及這些知識(shí)如何幫助我們避免類型錯(cuò)誤,并防止 JavaScript 中的內(nèi)存泄漏。還會(huì)研究?jī)?nèi)存管理與時(shí)間溢出之間的關(guān)系。
JavaScript 中強(qiáng)制類型在進(jìn)入 C++ 之前,先讓我們看看 JavaScript 是如何處理數(shù)據(jù)類型以及“類型強(qiáng)制”系統(tǒng)的一些陷阱的。
JavaScript 使用類型強(qiáng)制轉(zhuǎn)化自動(dòng)將一種數(shù)據(jù)類型轉(zhuǎn)換為另外一種:字符串轉(zhuǎn)為數(shù)字、數(shù)字轉(zhuǎn)為字符串、數(shù)字或字符串轉(zhuǎn)為布爾值等等。換句話說,如果你沒有明確指定所需的類型,JavaScript 將根據(jù)一組規(guī)則進(jìn)行猜測(cè)。有時(shí)這很管用,它可以幫助我們快速簡(jiǎn)潔地編寫代碼。但有時(shí)候可能是引發(fā)混亂的原因。
實(shí)際上即使這種行為從根本上來講是可預(yù)測(cè)的,但某些自動(dòng)推測(cè)也不那么直觀,并且在很多大型項(xiàng)目的代碼庫中,很容易看到類型強(qiáng)制轉(zhuǎn)換導(dǎo)致了意外錯(cuò)誤的發(fā)生。例如以下是使用組合字符串和數(shù)字的進(jìn)行運(yùn)算的一些演示:
"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
在這些例子中, + 運(yùn)算符造成了大量的混亂,它可以強(qiáng)制把字符串轉(zhuǎn)為數(shù)字,也可以作為連接運(yùn)算符組合兩個(gè)或多個(gè)字符串。
最后一個(gè)例子可能是最令人困惑的。在 "6" + 3?—?3 中,如果首先處理 3?—?3 ,然后再進(jìn)行字符串連接,"6" + 0 會(huì)返回一個(gè)字符串,但是在這里返回的結(jié)果居然是一個(gè)數(shù)字!
雖然類型強(qiáng)制轉(zhuǎn)換可以幫助開發(fā)人員更快速、簡(jiǎn)潔地編寫代碼,但是它使初學(xué)者思考得更少,從而也就不清楚為什么這樣的轉(zhuǎn)換系統(tǒng)可能會(huì)導(dǎo)致錯(cuò)誤,特別是在更大、更復(fù)雜的代碼庫中。上面的結(jié)果對(duì)于經(jīng)驗(yàn)豐富的 JavaScript 程序來說可能是完全合理的,但它們并不直觀!
考慮到 JavaScript 類型強(qiáng)制系統(tǒng)的優(yōu)點(diǎn)和缺點(diǎn),現(xiàn)在讓我們看看 C++ 是如何處理數(shù)據(jù)類型的。
C++ 中的類型和內(nèi)存管理C++ 之類的低級(jí)語言沒有這種潛在缺陷,因?yàn)楸仨氃诙x時(shí)聲明數(shù)據(jù)類型。雖然 JavaScript 也有三個(gè)關(guān)鍵字 ?var、 let 和 const? 用于聲明新變量,但在C ++中每個(gè)數(shù)據(jù)類型都有自己的關(guān)鍵字。
例如 C++ 中的 7 種基本數(shù)據(jù)類型是整型、浮點(diǎn)型、雙精度浮點(diǎn)型,字符型,寬字符型,布爾型和無類型。用于定義它們的關(guān)鍵字分別是 int、float、double、bool、char、wchar_t 和 void。
下面的代碼段包含了每種類型的示例聲明,并添加了注釋:
#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", "