摘要:如,不是定義常量么為什么還能改這就是我們今天要說(shuō)的重點(diǎn)中的堆內(nèi)存與棧內(nèi)存在引擎中對(duì)變量的存儲(chǔ)主要有兩種位置,堆內(nèi)存和棧內(nèi)存。而堆內(nèi)存首先要在堆內(nèi)存新分配存儲(chǔ)區(qū)域,之后又要把指針存儲(chǔ)到棧內(nèi)存中,效率相對(duì)就要低一些了。
最近跟著組里的大佬面試碰到這么一個(gè)問題,
Q:說(shuō)說(shuō)var、let、const的區(qū)別
A:balabalabalabla...
Q:const定義的值能改么?
A:你逗我?不能吧
不知道各位看官怎么想?答案是部分能改,部分不能改。const定義的基本類型不能改變,但是定義的對(duì)象是可以通過(guò)修改對(duì)象屬性等方法來(lái)改變的。如,
>>> const a = 1 >>> a <<< 1 >>> a = 2 <<< VM1750:1 Uncaught TypeError: Assignment to constant variable. at:1:3 (anonymous) @ VM1750:1 >>> const b = {} >>> b <<< {} >>> b.name = 1 >>> b <<< {name: 1} >>> b = {} <<< VM1785:1 Uncaught TypeError: Assignment to constant variable. at :1:4
const不是定義常量么?為什么還能改?這就是我們今天要說(shuō)的重點(diǎn)~
js中的堆內(nèi)存與棧內(nèi)存在js引擎中對(duì)變量的存儲(chǔ)主要有兩種位置,堆內(nèi)存和棧內(nèi)存。
和java中對(duì)內(nèi)存的處理類似,棧內(nèi)存主要用于存儲(chǔ)各種基本類型的變量,包括Boolean、Number、String、Undefined、Null,**以及對(duì)象變量的指針,這時(shí)候棧內(nèi)存給人的感覺就像一個(gè)線性排列的空間,每個(gè)小單元大小基本相等。
而堆內(nèi)存主要負(fù)責(zé)像對(duì)象Object這種變量類型的存儲(chǔ),如下圖
棧內(nèi)存中的變量一般都是已知大小或者有范圍上限的,算作一種簡(jiǎn)單存儲(chǔ)。而堆內(nèi)存存儲(chǔ)的對(duì)象類型數(shù)據(jù)對(duì)于大小這方面,一般都是未知的。個(gè)人認(rèn)為,這也是為什么null作為一個(gè)object類型的變量卻存儲(chǔ)在棧內(nèi)存中的原因。
因此當(dāng)我們定義一個(gè)const對(duì)象的時(shí)候,我們說(shuō)的常量其實(shí)是指針,就是const對(duì)象對(duì)應(yīng)的堆內(nèi)存指向是不變的,但是堆內(nèi)存中的數(shù)據(jù)本身的大小或者屬性是可變的。而對(duì)于const定義的基礎(chǔ)變量而言,這個(gè)值就相當(dāng)于const對(duì)象的指針,是不可變。
既然知道了const在內(nèi)存中的存儲(chǔ),那么const、let定義的變量不能二次定義的流程也就比較容易猜出來(lái)了,每次使用const或者let去初始化一個(gè)變量的時(shí)候,會(huì)首先遍歷當(dāng)前的內(nèi)存棧,看看有沒有重名變量,有的話就返回錯(cuò)誤。
說(shuō)到這里,有一個(gè)十分很容易忽略的點(diǎn),之前也是自己一直沒有注意的就是,使用new關(guān)鍵字初始化的之后是不存儲(chǔ)在棧內(nèi)存中的。為什么呢?new大家都知道,根據(jù)構(gòu)造函數(shù)生成新實(shí)例,這個(gè)時(shí)候生成的是對(duì)象,而不是基本類型。再看一個(gè)例子
var a = new String("123") var b = String("123") var c = "123" console.log(a==b, a===b, b==c, b===c, a==c, a===c) >>> true false true true true false console.log(typeof a) >>> "object"
我們可以看到new一個(gè)String,出來(lái)的是對(duì)象,而直接字面量賦值和工廠模式出來(lái)的都是字符串。但是根據(jù)我們上面的分析大小相對(duì)固定可預(yù)期的即便是對(duì)象也可以存儲(chǔ)在棧內(nèi)存的,比如null,為啥這個(gè)不是呢?再繼續(xù)看
var a = new String("123") var b = new String("123") console.log(a==b, a===b) >>> false false
很明顯,如果a,b是存儲(chǔ)在棧內(nèi)存中的話,兩者應(yīng)該是明顯相等的,就像null === null是true一樣,但結(jié)果兩者并不相等,說(shuō)明兩者都是存儲(chǔ)在堆內(nèi)存中的,指針指向不一致。
說(shuō)到這里,再去想一想我們常說(shuō)的值類型和引用類型其實(shí)說(shuō)的就是棧內(nèi)存變量和堆內(nèi)存變量,再想想值傳遞和引用傳遞、深拷貝和淺拷貝,都是圍繞堆棧內(nèi)存展開的,一個(gè)是處理值,一個(gè)是處理指針。
內(nèi)存分配和垃圾回收一般來(lái)說(shuō)棧內(nèi)存線性有序存儲(chǔ),容量小,系統(tǒng)分配效率高。而堆內(nèi)存首先要在堆內(nèi)存新分配存儲(chǔ)區(qū)域,之后又要把指針存儲(chǔ)到棧內(nèi)存中,效率相對(duì)就要低一些了。
垃圾回收方面,棧內(nèi)存變量基本上用完就回收了,而推內(nèi)存中的變量因?yàn)榇嬖诤芏嗖淮_定的引用,只有當(dāng)所有調(diào)用的變量全部銷毀之后才能回收。
繼續(xù)往下思考的話,其中還有很多的東西需要去學(xué)習(xí),今天先到這里,后續(xù)再來(lái)補(bǔ)充。
話說(shuō)~NaN會(huì)不會(huì)也是存儲(chǔ)在堆內(nèi)存中的呢?大家想想吧,歡迎大家來(lái)一起討論討論~文中如有錯(cuò)誤歡迎指出~
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/96984.html
摘要:堆與棧棧由編譯器自動(dòng)分配存放函數(shù)的參數(shù)值局部變量的值等其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧堆一般由程序員分配釋放若程序員不釋放程序結(jié)束時(shí)可能由回收這里是指操作系統(tǒng)區(qū)別和聯(lián)系申請(qǐng)方式堆由程序員自己申請(qǐng)并指明大小在語(yǔ)言中的函數(shù)棧由系統(tǒng)自動(dòng)分配聲明在函 堆與棧 棧(stack): 由編譯器自動(dòng)分配, 存放函數(shù)的參數(shù)值, 局部變量的值等. 其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧. 堆(heap): 一般由...
摘要:一前言的垃圾回收機(jī)制使用垃圾回收機(jī)制來(lái)自動(dòng)管理內(nèi)存。垃圾回收器只會(huì)針對(duì)新生代內(nèi)存區(qū)老生代指針區(qū)以及老生代數(shù)據(jù)區(qū)進(jìn)行垃圾回收。分別對(duì)新生代和老生代使用不同的垃圾回收算法來(lái)提升垃圾回收的效率。 V8 實(shí)現(xiàn)了準(zhǔn)確式 GC,GC 算法采用了分代式垃圾回收機(jī)制。因此,V8 將內(nèi)存(堆)分為新生代和老生代兩部分。 一、前言 V8的垃圾回收機(jī)制:JavaScript使用垃圾回收機(jī)制來(lái)自動(dòng)管理內(nèi)存。垃...
摘要:而堆內(nèi)存主要負(fù)責(zé)像對(duì)象這種變量類型的存儲(chǔ),如下圖引用類型中復(fù)制淺拷貝的只是棧內(nèi)存中的指針,指向同一個(gè)堆內(nèi)存的對(duì)象如何實(shí)現(xiàn)深拷貝最簡(jiǎn)單的方法就是與方法 淺拷貝只會(huì)在引用類型中出現(xiàn) 基本數(shù)據(jù)類型有哪些,number,string,boolean,null,undefined,symbol以及未來(lái)ES10新增的BigInt(任意精度整數(shù))七類。 引用數(shù)據(jù)類型(Object類)有常規(guī)名值對(duì)的無(wú)...
摘要:所以相對(duì)于簡(jiǎn)單數(shù)據(jù)類型而言,他們占用內(nèi)存比較小,如果放在堆中,查找會(huì)浪費(fèi)很多時(shí)間,而把堆中的數(shù)據(jù)放入棧中也會(huì)影響棧的效率。六總結(jié)本文總結(jié)了數(shù)據(jù)類型及其聲明賦值更新時(shí)在內(nèi)存堆棧中的表現(xiàn),可以更深入的理解這些數(shù)據(jù)類型。 JS數(shù)據(jù)類型 與 內(nèi)存堆棧 一、前言 JS的數(shù)據(jù)類型已經(jīng)是大家都很熟悉的東西了,但是大家是否對(duì)這些數(shù)據(jù)類型在內(nèi)存中的分配了解,甚至在操作這些變量時(shí),內(nèi)存中是如何表現(xiàn)的,本文...
摘要:內(nèi)存空間又被分為兩種,棧內(nèi)存與堆內(nèi)存。今天就堆棧隊(duì)列的內(nèi)容就大概說(shuō)到這里下一篇博客在繼續(xù)說(shuō)一下,有什么說(shuō)的不對(duì)或者不足的地方,請(qǐng)大家批評(píng)指正 棧的定義 棧是計(jì)算機(jī)科學(xué)中的一種抽象數(shù)據(jù)類型,只允許在有序的線性數(shù)據(jù)集合的一端(稱為堆棧頂端,英語(yǔ):top)進(jìn)行加入數(shù)據(jù)(英語(yǔ):push)和移除數(shù)據(jù)(英語(yǔ):pop)的運(yùn)算。因而按照后進(jìn)先出(LIFO, Last In First Out)的原理運(yùn)...
閱讀 2883·2021-11-24 09:39
閱讀 2455·2019-08-30 15:53
閱讀 3025·2019-08-30 13:47
閱讀 1296·2019-08-30 12:50
閱讀 1481·2019-08-29 16:31
閱讀 2642·2019-08-29 13:14
閱讀 1559·2019-08-29 10:55
閱讀 790·2019-08-26 13:32