日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

javascript --- 堆栈内存与闭包的作用

發布時間:2023/12/10 javascript 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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 需要了解的

  • 函數上下文: JS中每一個函數在執行的時候都會創建一個執行上下文
  • 堆內存: 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的值并未改變.這引出了閉包的第二個作用,保護全局變量.

    總結

    以上是生活随笔為你收集整理的javascript --- 堆栈内存与闭包的作用的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。