成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript 是如何工作的:JavaScript 的內(nèi)存模型

baoxl / 3582人閱讀

摘要:調(diào)用堆棧是存放原始數(shù)據(jù)類型的地方除了函數(shù)調(diào)用之外。上一節(jié)中聲明變量后調(diào)用堆棧的粗略表示如下。解釋改變的正確方法是更改內(nèi)存地址。在聲明時,將在調(diào)用堆棧上分配內(nèi)存地址,該值是在堆上分配的內(nèi)存地址。

這是專門探索 JavaScript 及其所構(gòu)建的組件的系列文章的第 21 篇。

想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你!

如果你錯過了前面的章節(jié),可以在這里找到它們:

JavaScript 是如何工作的:引擎,運(yùn)行時和調(diào)用堆棧的概述!

JavaScript 是如何工作的:深入V8引擎&編寫優(yōu)化代碼的5個技巧!

JavaScript 是如何工作的:內(nèi)存管理+如何處理4個常見的內(nèi)存泄漏!

JavaScript 是如何工作的:事件循環(huán)和異步編程的崛起+ 5種使用 async/await 更好地編碼方式!

JavaScript 是如何工作的:深入探索 websocket 和HTTP/2與SSE +如何選擇正確的路徑!

JavaScript 是如何工作的:與 WebAssembly比較 及其使用場景!

JavaScript 是如何工作的:Web Workers的構(gòu)建塊+ 5個使用他們的場景!

JavaScript 是如何工作的:Service Worker 的生命周期及使用場景!

JavaScript 是如何工作的:Web 推送通知的機(jī)制!

JavaScript 是如何工作的:使用 MutationObserver 跟蹤 DOM 的變化!

JavaScript 是如何工作的:渲染引擎和優(yōu)化其性能的技巧!

JavaScript 是如何工作的:深入網(wǎng)絡(luò)層 + 如何優(yōu)化性能和安全!

JavaScript 是如何工作的:CSS 和 JS 動畫底層原理及如何優(yōu)化它們的性能!

JavaScript 是如何工作的:解析、抽象語法樹(AST)+ 提升編譯速度5個技巧!

JavaScript 是如何工作的:深入類和繼承內(nèi)部原理+Babel和 TypeScript 之間轉(zhuǎn)換!

JavaScript 是如何工作的:存儲引擎+如何選擇合適的存儲API!

JavaScript 是如何工作的:Shadow DOM 的內(nèi)部結(jié)構(gòu)+如何編寫?yīng)毩⒌慕M件!

JavaScript 是如何工作的:WebRTC 和對等網(wǎng)絡(luò)的機(jī)制!

JavaScript 是如何工作的:編寫自己的 Web 開發(fā)框架 + React 及其虛擬 DOM 原理!

JavaScript 是如何工作的:模塊的構(gòu)建以及對應(yīng)的打包工具

// 聲明一些變量并初始化它們
var a = 5
let b = "xy"
const c = true

// 分配新值
a = 6
b = b + "z"
c = false //  類型錯誤:不可對常量賦值

作為程序員,聲明變量、初始化變量(或不初始化變量)以及稍后為它們分配新值是我們每天都要做的事情。

但是當(dāng)這樣做的時候會發(fā)生什么呢? JavaScript 如何在內(nèi)部處理這些基本功能? 更重要的是,作為程序員,理解 JavaScript 的底層細(xì)節(jié)對我們有什么好處。

下面,我打算介紹以下內(nèi)容:

JS 原始數(shù)據(jù)類型的變量聲明和賦值

JavaScript內(nèi)存模型:調(diào)用堆棧和堆

JS 引用類型的變量聲明和賦值

let vs const

JS 原始數(shù)據(jù)類型的變量聲明和賦值

讓我們從一個簡單的例子開始。下面,我們聲明一個名為myNumber的變量,并用值23初始化它。

let myNumber = 23

當(dāng)執(zhí)行此代碼時,JS將執(zhí)行:

為變量(myNumber)創(chuàng)建唯一標(biāo)識符(identifier)。

在內(nèi)存中分配一個地址(在運(yùn)行時分配)。

將值 23 存儲在分配的地址。

雖然我們通俗地說,“myNumber 等于 23”,更專業(yè)地說,myNumber 等于保存值 23 的內(nèi)存地址,這是一個值得理解的重要區(qū)別。

如果我們要創(chuàng)建一個名為 newVar 的新變量并把 myNumber 賦值給它。

let newVar = myNumber

因?yàn)?myNumber 在技術(shù)上實(shí)際是等于 “0012CCGWH80”,所以 newVar 也等于 “0012CCGWH80”,這是保存值為23的內(nèi)存地址。通俗地說就是 newVar 現(xiàn)在的值為 23

因?yàn)?myNumber 等于內(nèi)存地址 0012CCGWH80,所以將它賦值給 newVar 就等于將0012CCGWH80 賦值給 newVar

現(xiàn)在,如果我這樣做會發(fā)生什么:

myNumber = myNumber + 1

myNumber的值肯定是 24。但是newVar的值是否也為 24 呢?,因?yàn)樗鼈冎赶蛳嗤膬?nèi)存地址?

答案是否定的。由于JS中的原始數(shù)據(jù)類型是不可變的,當(dāng) myNumber + 1 解析為24時,JS 將在內(nèi)存中分配一個新地址,將24作為其值存儲,myNumber將指向新地址。

這是另一個例子:

let myString = "abc"
myString = myString + "d"

雖然一個初級 JS 程序員可能會說,字母d只是簡單在原來存放adbc內(nèi)存地址上的值,從技術(shù)上講,這是錯的。當(dāng) abcd 拼接時,因?yàn)樽址彩荍S中的基本數(shù)據(jù)類型,不可變的,所以需要分配一個新的內(nèi)存地址,abcd 存儲在這個新的內(nèi)存地址中,myString 指向這個新的內(nèi)存地址。

下一步是了解原始數(shù)據(jù)類型的內(nèi)存分配位置。

JavaScript 內(nèi)存模型:調(diào)用堆棧和堆

JS 內(nèi)存模型可以理解為有兩個不同的區(qū)域:調(diào)用堆棧(call stack)堆(heap)

調(diào)用堆棧是存放原始數(shù)據(jù)類型的地方(除了函數(shù)調(diào)用之外)。上一節(jié)中聲明變量后調(diào)用堆棧的粗略表示如下。

在上圖中,我抽象出了內(nèi)存地址以顯示每個變量的值。 但是,不要忘記實(shí)際上變量指向內(nèi)存地址,然后保存一個值。 這將是理解 let vs. const 一節(jié)的關(guān)鍵。

是存儲引用類型的地方。跟調(diào)用堆棧主要的區(qū)別在于,堆可以存儲無序的數(shù)據(jù),這些數(shù)據(jù)可以動態(tài)地增長,非常適合數(shù)組和對象。

JS 引用類型的變量聲明和賦值

讓我們從一個簡單的例子開始。下面,我們聲明一個名為myArray的變量,并用一個空數(shù)組初始化它。

let myArray = []

當(dāng)你聲明變量“myArray”并為其指定非原始數(shù)據(jù)類型(如“[]”)時,以下是在內(nèi)存中發(fā)生的情況:

為變量創(chuàng)建唯一標(biāo)識符(“myArray”)

在內(nèi)存中分配一個地址(將在運(yùn)行時分配)

存儲在堆上分配的內(nèi)存地址的值(將在運(yùn)行時分配)

堆上的內(nèi)存地址存儲分配的值(空數(shù)組[])

從這里,我們可以 push, pop,或?qū)?shù)組做任何我們想做的。

myArray.push("first")
myArray.push("second")
myArray.push("third")
myArray.push("fourth")
myArray.pop()

let vs const

一般來說,我們應(yīng)該盡可能多地使用const,只有當(dāng)我們知道某個變量將發(fā)生改變時才使用let。

讓我們明確一下我們所說的“改變”是什么意思。

let sum = 0
sum = 1 + 2 + 3 + 4 + 5
let numbers = []
numbers.push(1)
numbers.push(2)
numbers.push(3)
numbers.push(4)
numbers.push(5)

這個程序員使用let正確地聲明了sum,因?yàn)樗麄冎乐禃淖?。但是,這個程序員使用let錯誤地聲明了數(shù)組 numbers ,因?yàn)樗麑褨|西推入數(shù)組理解為改變數(shù)組的值。

解釋“改變”的正確方法是更改內(nèi)存地址。let 允許你更改內(nèi)存地址。const 不允許你更改內(nèi)存地址。

const importantID = 489
importantID = 100 // 類型錯誤:賦值給常量變量

讓我們想象一下這里發(fā)生了什么。

當(dāng)聲明importantID時,分配了一個內(nèi)存地址,并存儲489的值。記住,將變量importantID看作等于內(nèi)存地址。

當(dāng)將100分配給importantID時,因?yàn)?b>100是一個原始數(shù)據(jù)類型,所以會分配一個新的內(nèi)存地址,并將100的值存儲這里。

然后 JS 嘗試將新的內(nèi)存地址分配給 importantID,這就是拋出錯誤的地方,這也是我們想要的行為,因?yàn)槲覀儾幌敫淖冞@個 importantID的值。

當(dāng)你將100分配給importantID時,實(shí)際上是在嘗試分配存儲100的新內(nèi)存地址,這是不允許的,因?yàn)?b>importantID是用const聲明的。

如上所述,假設(shè)的初級JS程序員使用let錯誤地聲明了他們的數(shù)組。相反,他們應(yīng)該用const聲明它。這在一開始看起來可能令人困惑,我承認(rèn)這一點(diǎn)也不直觀。

初學(xué)者會認(rèn)為數(shù)組只有在我們可以改變的情況下才有用,const 使數(shù)組不可變,那么為什么要使用它呢? 請記住:“改變”是指改變內(nèi)存地址。讓我們深入探討一下為什么使用const聲明數(shù)組是完全可以的。

const myArray = []

在聲明 myArray 時,將在調(diào)用堆棧上分配內(nèi)存地址,該值是在堆上分配的內(nèi)存地址。堆上存儲的值是實(shí)際的空數(shù)組。想象一下,它是這樣的:

如果我們這么做:

myArray.push(1)
myArray.push(2)
myArray.push(3)
myArray.push(4)
myArray.push(5)

執(zhí)行 push 操作實(shí)際是將數(shù)字放入堆中存在的數(shù)組。而 myArray 的內(nèi)存地址沒有改變。這就是為什么雖然使用const聲明了myArray,但沒有拋出任何錯誤。

myArray 仍然等于 0458AFCZX91,它的值是另一個內(nèi)存地址22VVCX011,它在堆上有一個數(shù)組的值。

如果我們這樣做,就會拋出一個錯誤:

myArray = 3

由于 3 是一個原始數(shù)據(jù)類型,因此生成一個新的調(diào)用堆棧上的內(nèi)存地址,其值為 3,然后我們將嘗試將新的內(nèi)存地址分配給 myArray,由于myArray是用const聲明的,所以這是不允許的。

另一個會拋出錯誤的例子:

myArray = ["a"]

由于[a]是一個新的引用類型的數(shù)組,因此將分配調(diào)用堆棧上的一個新內(nèi)存地址,并存儲上的一個內(nèi)存地址的值,其它值為 [a]。然后,我們嘗試將調(diào)用堆棧內(nèi)存地址分配給 myArray,這會拋出一個錯誤。

對于使用const聲明的對象(如數(shù)組),由于對象是引用類型,因此可以添加鍵,更新值等等。

const myObj = {}
myObj["newKey"] = "someValue" // 這不會拋出錯誤

為什么這些知識對我們有用呢

JavaScript 是世界上排名第一的編程語言(根據(jù)GitHub和Stack Overflow的年度開發(fā)人員調(diào)查)。 掌握并成為“JS忍者”是我們所有人都渴望成為的人。

任何質(zhì)量好的的 JS 課程或書籍都提倡使用let, const 來代替 var,但他們并不一定說出原因。 對于初學(xué)者來說,為什么某些 const 變量在“改變”其值時會拋出錯誤而其他 const變量卻沒有。 對我來說這是有道理的,為什么這些程序員默認(rèn)使用let到處避免麻煩。

但是,不建議這樣做。谷歌擁有世界上最好的一些程序員,在他們的JavaScript風(fēng)格指南中說,使用 constlet 聲明所有本地變量。默認(rèn)情況下使用 const,除非需要重新分配變量,不使用 var 關(guān)鍵字(原文)。

雖然他們沒有明確說明原因,但據(jù)我所知,有幾個原因

先發(fā)制人地限制未來的 bug。

使用 const 聲明的變量必須在聲明時初始化,這迫使程序員經(jīng)常在范圍方面更仔細(xì)地放置它們。這最終會導(dǎo)致更好的內(nèi)存管理和性能。

要通過代碼與任何可能遇到它的人交流,哪些變量是不可變的(就JS而言),哪些變量可以重新分配。

希望上面的解釋能幫助你開始明白為什么或者什么時候應(yīng)該在代碼中使用 letconst 。

代碼部署后可能存在的BUG沒法實(shí)時知道,事后為了解決這些BUG,花了大量的時間進(jìn)行l(wèi)og 調(diào)試,這邊順便給大家推薦一個好用的BUG監(jiān)控工具 Fundebug。

你的點(diǎn)贊是我持續(xù)分享好東西的動力,歡迎點(diǎn)贊!

交流

干貨系列文章匯總?cè)缦?,覺得不錯點(diǎn)個Star,歡迎 加群 互相學(xué)習(xí)。

https://github.com/qq44924588...

我是小智,公眾號「大遷世界」作者,對前端技術(shù)保持學(xué)習(xí)愛好者。我會經(jīng)常分享自己所學(xué)所看的干貨,在進(jìn)階的路上,共勉!

關(guān)注公眾號,后臺回復(fù)福利,即可看到福利,你懂的。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/103530.html

相關(guān)文章

  • JavaScript 如何工作JavaScript 共享傳遞和按值傳遞

    摘要:它對數(shù)組和對象使用按值傳遞,但這是在的共享傳參或拷貝的引用中使用的按值傳參。例如在這里,變量和值在執(zhí)行期間存儲在堆棧中。返回值這是可選的,函數(shù)可以返回值,也可以不返回值。變量被推入堆棧,從而在執(zhí)行時成為的副本。 這是專門探索 JavaScript 及其所構(gòu)建的組件的系列文章的第 22 篇。 想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你! 如果你錯過了前面的章節(jié),可...

    keithyau 評論0 收藏0
  • JavaScript 如何工作JavaScript 共享傳遞和按值傳遞

    摘要:它對數(shù)組和對象使用按值傳遞,但這是在的共享傳參或拷貝的引用中使用的按值傳參。例如在這里,變量和值在執(zhí)行期間存儲在堆棧中。返回值這是可選的,函數(shù)可以返回值,也可以不返回值。變量被推入堆棧,從而在執(zhí)行時成為的副本。 這是專門探索 JavaScript 及其所構(gòu)建的組件的系列文章的第 22 篇。 想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你! 如果你錯過了前面的章節(jié),可...

    陳偉 評論0 收藏0
  • JavaScript工作原理(六):WebAssembly比較分析和特定情況下最好在JavaScri

    摘要:我們將拆分來分析它的工作原理,更重要的是,它在性能方面如何提升加載時間,執(zhí)行速度,垃圾回收,內(nèi)存使用率,平臺訪問,調(diào)試,多線程和可移植性。目前,是圍繞和用例設(shè)計的。多線程在單個線程上運(yùn)行。目前不支持多線程。被設(shè)計為安全和便攜。 我們將拆分WebAssembly來分析它的工作原理,更重要的是,它在性能方面如何提升JavaScript:加載時間,執(zhí)行速度,垃圾回收,內(nèi)存使用率,平臺API訪...

    novo 評論0 收藏0
  • JavaScript 如何工作系列文章已更新到22篇

    摘要:為了方便大家共同學(xué)習(xí),整理了之前博客系列的文章,目前已整理是如何工作這個系列,可以請猛戳博客查看。以下列出該系列目錄,歡迎點(diǎn)個星星,我將更友動力整理理優(yōu)質(zhì)的文章,一起學(xué)習(xí)。 為了方便大家共同學(xué)習(xí),整理了之前博客系列的文章,目前已整理 JavaScript 是如何工作這個系列,可以請猛戳GitHub博客查看。 以下列出該系列目錄,歡迎點(diǎn)個星星,我將更友動力整理理優(yōu)質(zhì)的文章,一起學(xué)習(xí)。 J...

    lx1036 評論0 收藏0
  • 【譯】JavaScript面試問題:事件委托和this

    摘要:主題來自于的典型面試問題列表。有多種方法來處理事件委托。這種方法的缺點(diǎn)是父容器的偵聽器可能需要檢查事件來選擇正確的操作,而元素本身不會是一個監(jiān)聽器。 showImg(http://fw008950-flywheel.netdna-ssl.com/wp-content/uploads/2014/11/Get-Hired-Fast-How-to-Job-Search-Classifieds...

    浠ラ箍 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<