javascript --- 堆棧內存與閉包的作用

你可能會用到的

  • 堆內存: 存儲引用類型值所在的空間
  • 棧內存: 存儲基本類型值和存儲代碼所在空間
  • 函數上下文: JS每一個函數在執行的時候都會創建一個執行上下文

1. 堆內存中的數字和字符串都是相等的

let a = {}, b='0', c=0;
a[b] = 'marron';
a[c] = 'Mar'
console.log(a[b]) // Mar
  • 第一行代碼, a創建是一個對象,對象在JS中是引用類型,因此會創建一個堆內存來存儲對象
// 堆: AAAFFF00
(此時里面是空的)
  • 此時a的值實際上是指向這個堆的地址,即A = AAAFFF00
  • 在執行 a[b] = 'marron'時,實際上會給堆內存中鍵為’0’賦上值 ‘marron’
// 堆: AAAFFF00
'0': 'marron' 
  • 在執行a[c] = 'Mar'時,由于堆中字符串和數字默認是相等的,此時堆內存中實際的操作是:
// 堆: AAAFFF00
+ '0': 'Mar'
  • 因此最后輸出的回收’Mar’

2.對象作為值在堆內存中都會隱式調用toString方法,變為字符串

let a = {},b = {n: '1'},c = {m: '2'}
a[b] = 'marron'
a[c] = 'Mar'
console.log(a[b]);		// 'Mar'
// 在堆內存中都是   { '[object object]': 'Mar' }
  • 執行a= {}時,
// 堆: AAAFFF01
  • 此時 a = AAAFFF01
  • 執行a[b] = 'marron'
  • 會先隱式調用b.toString(),然后將得到的結果存放到 堆AAAFFF01中
// 堆: AAAFFF01
'[Object Object]': 'marron'
  • 執行a[c] = 'Mar',同理
// 堆: AAAFFF01
'[Object Object]': 'Mar'
  • 因此,最后會輸出 ‘Mar’

3. 閉包問題

var test = (function(i){return function(){alert(i *= 2)}
})(2)
test(5)

3.1 需要了解的

  1. 函數上下文: JS中每一個函數在執行的時候都會創建一個執行上下文
  2. 堆內存: JS中每一個引用類型的操作,都對應一個堆內存

3.2 解析

  • var test = (function(i){...})(2),等號右邊是一個自執行函數.執行函數的時候會創建一個執行上下文
// 自執行函數的執行上下文
i = 2;
return function(){}
  • 遇到return function(){}中的function是一個引用類型,故會創建一個堆內存
// 堆: AAAFFF00
"alert(i *=2)"
...
  • 然后將堆內存的地址返回,此時堆內存的上一級作用域是自執行函數的執行上下文
// 自執行函數的 執行上下文
i = 2;
return AAAFFF00
  • 此時test的值是堆的內存地址: test = AAAFFF00
  • 之后遇到了 test(5),函數執行會創建一個執行上下文
// test(5)的 執行上下文
->: AAAFFF11
  • 然后順著地址去找到堆AAAFFF11,找到堆AAAFFF11之后,遇到函數代碼字符串. alert( i *= 2),
// test(5)的 執行上下文
"alert( i*= 2)"
  • 由于當前堆中沒用i的值,會順著作用域鏈,往上級作用域尋找,找到了 自執行函數的上下文.然后回彈出字符串 “4”,同時堆內存中i的值被改成了4

  • 完畢之后,由于test(5)的執行上下文中沒用變量被引用,會根據JS的垃圾回收機制,進行銷毀.

  • 自執行函數的 執行上下文中的變量i被堆AAAFFF11引用,會一直存在,因此形成了閉包.

4. 閉包小練手

var a = 0,b = 0;
function A(a){A = function(b){alert(a + b++);};alert(a++)
}
A(1);
A(2);
  • 首先有個全局作用域
// global
a = 0;
b = 0;
A =: FFFAAA00
ctx:A(1)
ctx:A(2)
  • 執行到A(1)
// ctx: A(1)
a(局部) = 1
A(全局) =: FFFAAA01
alert(a++)	 // 會彈出'1',此時局部a = 2
// 由于a被堆: FFFAAA01 引用,因此結束時, ctx: A(1)不會被清除,形成了閉包喲.
  • A(1)執行完畢,此時全局作用域
// global
a = 0;
b = 0;
A =: FFFAAA01
ctx: A(2)  <-- 執行到這一行
  • A(2)開始執行
// ctx: A(2) 傳入參數由b接收
a(ctx(A(1))) = 2;
b(局部) = 2;
alert(a + b++); // 彈出'4', 然后局部b = 3
// 完畢后,作用域銷毀
// 注: A此時執行的是堆: AAAFFF01,堆并未消失
  • 綜上所述,會彈出’1’,‘4’

說明: 上面執行了2次A函數,且分別用到了a , b變量…但是在對a,b變量操作完成后.全局變量的a和b的值并未改變.這引出了閉包的第二個作用,保護全局變量.

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/250321.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/250321.shtml
英文地址,請注明出處:http://en.pswp.cn/news/250321.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python_sting字符串的方法及注釋

string類型是python內置的類型&#xff0c;無需安裝 方法/屬性說明 capitalize() 把字符串的第一個字符改為大寫 casefold() 把整個字符串的所有字符改為小寫 center(width) 將字符串居中&#xff0c;并使用空格填充至長度width的新字符串 count(sub[,start[,end]]) …

作業3

import turtle turtle.bgcolor(red) turtle.color(yellow)turtle.fillcolor(yellow) turtle.begin_fill() for i in range(5):turtle.forward(100)turtle.right(144) turtle.end_fill() turtle.done()轉載于:https://www.cnblogs.com/zhangkef97/p/9016608.html

javascript --- [小練習]變量提升、優先級綜合

求下列函數輸出結果 function Foo() {getName function() {console.log(1)}return this } Foo.getName function() {console.log(2) } Foo.prototype.getName function() {console.log(3) } var getName function() {console.log(4) }function getName() {console.log(5) …

Confluence 6 自定義 Decorator 模板的宏和針對高級用戶

宏 頁面的某些部分使用的是 Velocity 宏進行創建的&#xff0c;包括導航欄。有關宏的創建&#xff0c;你可以參考頁面 Working With Decorator Macros 頁面中的內容。 針對高級用戶 velocity 目錄是 Confluence 首先進行模板搜索的查找路徑。你可以對 Confluence 的 velocity …

Matlab之rand(), randn(), randi()函數的使用方法

1. rand()函數用于生成取值在&#xff08;0~1&#xff09;之間均勻分布的偽隨機數。rand(n)&#xff1a;生成n*n的0~1之間的滿足均勻分布的偽隨機矩陣&#xff1b;rand(m,n)&#xff1a;生成m*n的偽隨機數&#xff1b;rand(m,n,double)&#xff1a;生成m*n的雙精度偽隨機數&am…

javascript --- [有趣的條件]雙等號的隱式調用和數據劫持

1 雙等號的隱式調用和數據劫持 求下面條件,在a為什么樣時,等號成立 if(a 1 && a 2 && a 3){console.log(等號成立) }1.1 雙等號的隱式轉換 首先得了解雙等號的隱式轉換規則 等式備注對象 字符串隱式調用 toString方法將對象轉換成字符串null undeifne…

分組查詢

1、簡單分組查詢 語法形式&#xff1a; select function() from table_name where condition group by field; 進行分組查詢時&#xff0c;分組所依據的字段上的值一定要有重復值&#xff0c;否則分組沒有任何意義。 2、實現統計功能分組查詢 關鍵字group by單獨使用時&#xf…

深入探討多模態模型和計算機視覺

近年來&#xff0c;機器學習領域在從圖像識別到自然語言處理的不同問題類型上取得了顯著進展。然而&#xff0c;這些模型中的大多數都對來自單一模態的數據進行操作&#xff0c;例如圖像、文本或語音。相比之下&#xff0c;現實世界的數據通常來自多種模態&#xff0c;例如圖像…

移動硬盤函數不正確要如何尋回資料

移動磁盤打不開函數不正確&#xff0c;是因為這個I盤的文件系統內部結構損壞導致的。要恢復里面的數據就必須要注意&#xff0c;這個盤不能格式化&#xff0c;否則數據會進一步損壞。具體的恢復方法看正文 工具/軟件&#xff1a;AuroraDataRecovery 步驟1&#xff1a;先百度搜索…

vue --- [全家桶]vue-router

1. Vue - router Vue Router是 Vue.js 官方的路由管理器它和Vue.js的核心深度集成,可以非常方便的用于SPA應用程序的開發 Vue Router包含的功能有: 支持HTML5歷史模式或hash模式支持嵌套路由支持路由參數支持編程式路由支持命名路由 <div id"app"><rout…

HashMap的四種訪問方式

第一種&#xff1a;通過Map.entrySet使用iterator遍歷key和value 1 public void visit_1(HashMap<String,Integer> hm){ 2 Iterator<Map.Entry<String,Integer>> it hm.entrySet().iterator(); 3 while(it.hasNext()){ 4 Map.Entry<String ,Integer> …

16.unix網絡編程一卷 unp.h

unix網絡編程 --ubuntu下建立編譯環境 1.安裝編譯器&#xff0c;安裝build-essential sudo apt-get install build-essential 2.下載本書的頭文件 下載unp13e&#xff1a; http://pix.cs.olemiss.edu/csci561/prg561.1.html 3.進入unp13e 查看readme&#xff0c;照下列提示操作…

webpack --- [讀書筆記] webpack中常用的一些配置項

1. Webpack 當前Web開發面臨的困境 文件依賴關系錯綜復雜靜態資源請求效率低模塊化支持不友好瀏覽器對高級JavaScript特性兼容程度低 1.1 webpack概述 webpack是一個流行的前端項目構建工具,可以解決當前web開發中所面臨的困境. webpack提供了友好的模塊化支持,以及代碼壓…

spring中bean的作用域屬性single與prototype的區別

https://blog.csdn.net/linwei_1029/article/details/18408363 轉載于:https://www.cnblogs.com/stanljj/p/9907444.html

windows程序設計.第一個windos程序

Windows程序設計&#xff08;第5版&#xff09; windows程序需要調用API。 第一個Windows程序 1 /*HelloMsg.c -- Displays "Hello World!" in a message box*/ 2 #include <Windows.h> 3 4 int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE…

java接口練習2

1、編寫2個接口&#xff1a;InterfaceA和InterfaceB&#xff1b;在接口InterfaceA中有個方法voidprintCapitalLetter()&#xff1b;在接口InterfaceB中有個方法void printLowercaseLetter()&#xff1b;然后寫一個類Print實現接口InterfaceA和InterfaceB&#xff0c;要求printC…

vue --- [全家桶] Vuex

1. Vuex 概述 1.1 組件之間共享數據的方式 父向子傳值: v-bind 屬性綁定子向父傳值: v-on 事件綁定兄弟組件之間共享數據: EventBus$on: 接收數據的那個組件$emit: 發送數據的那個組件 1.2 Vuex是什么 Vuex: 是實現組件全局狀態(數據)管理的一種機制,可以方便的實現組件之間…

C#/WPF程序開機自動啟動

最近一個C/S項目客戶要求開機自啟的功能&#xff0c;網上找了一些方法&#xff0c;不頂用&#xff1b;最后自己去翻書&#xff0c;找到了這段代碼&#xff0c;親測可用&#xff0c;Wpf環境下需要改下獲取程序目錄的方式即可&#xff0c;Winform直接可用。 1 #regio…

github --- 多個項目的管理方式

1. 多個項目管理方式 進入項目根目錄: git init 將當前的項目添加到暫存區中: git add . (注意: 最后有一個點) 將暫存區的內容放到本地倉庫: git commit -m 初始化項目 登錄github , 新建遠程倉庫 在本地添加遠程倉庫的源: git remote origin https://github.com/Lizhhhh/…

記錄一個坑

導入項目后運行控制臺打印異常,pom都已檢查,沒有任何問題 解決辦法: 項目右擊---properties---deployment assembly---add---java build path entries---maven deoendencies 保存并關閉 解決... 這個問題第一次遇到 檢查了很多遍maven的依賴,明明都已經配置好了 ,仍然產生了…