精品伊人久久大香线蕉,开心久久婷婷综合中文字幕,杏田冲梨,人妻无码aⅴ不卡中文字幕

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
用一個例子理解JS函數的底層處理機制

個人筆記,如有錯誤煩請指正

以下面代碼的運行舉例,一行行進行運行的解析

var x = [12, 23];
function fn(y) {
    y[0] = 100;
    y = [100];
    y[1] = 200;
    console.log(y);
}
fn(x);
console.log(x);

var x = [12, 23];運行如下

  1. 開辟堆內存,創建數組值,假設堆內存的地址為0x000000
  2. 聲明變量x
  3. 賦值,即將x指向堆內存的地址0x000000

接著

function fn(y) {
    y[0] = 100;
    y = [100];
    y[1] = 200;
    console.log(y);
}

運行如下

上面這段代碼是創建一個函數的過程。和創建一個變量類似:

  • 都是聲明一個變量存儲值
  • 步驟一樣:第一步也是先創建一個堆內存,里面存的是函數,這個堆內存有一個地址,然后把地址賦值給變量
  • 聲明:方式類似函數名也算變量,當我們聲明函數function fn(y){...}時,相當于我們聲明了一個變量,只不過值是函數。類似于var fn = function (y){...}的函數表達式。最終把一個函數作為值賦值給一個變量或者其他

所以創建一個函數,詳細的執行順序如下

  1. 首先開辟一個堆內存,存儲函數的值(假設地址為0x000001)
    • 對象的值在堆內存當中,存儲的是它的鍵值對
    • 函數的值在堆內存當中,存儲的是它的代碼,而且是以字符串的形式存儲的
    • 創建函數的時候,就聲明了它的作用域(scope),scope值是當前創建函數的時候所處的上下文,即在哪個上下文中創建的,作用域就是誰
  2. 接著聲明變量fn,并且指向堆內存地址(假設為0x000001)

函數執行的步驟

fn(x);運行如下(函數執行的步驟)

  1. 函數執行時,永遠傳的是值,fn(x)傳的是x的值,即x指向的0x000000堆內存地址
  2. fn(0x000000)形成一個全新的私有上下文EC(fn)
  3. 在函數形成的新的上下文中,生成一個私有化變量對象AO,用來存儲當前上下文中聲明的變量(Active Object活動對象,簡稱AO,變量對象的一種,類似全局上下文中的全局變量)
  4. 內部代碼執行之前發生的事
    • 初始化作用域鏈scope-chain <EC(fn1),EC(G)>,鏈的兩頭是 <當前自己的私有上下文,函數的作用域(創建函數的時候所在的上下文)>,鏈的右側也叫當前上下文的'上級上下文'
    • 初始化this
    • 初始化argument
    • 在當前上下文中,聲明一個形參變量,并且把傳遞的實參值賦值給它
    • 變量提升
  5. 進棧執行代碼
  6. 出棧釋放

函數進棧執行代碼的詳細步驟

接著說說上面第5步的詳細步驟

把之前創建的函數,在堆內存中存儲的代碼字符串拿出來轉換為代碼一行一行的執行執行。

私有上下文中代碼執行中如果遇到一個變量,首先看是否為自己的'私有變量',如果是'私有'的,則操作自己的,和外界沒有必然的關系,如果不是自己私有的,則基于作用域鏈,向其上級上下文中查找,看是否為上級上下文中私有的,如果也不是,繼續向上查找......一直找到EC(G)全局上下文為止,我們把這種查找過程稱之為 作用域鏈查找機制
所以

y[0] = 100
y = [100]
y[1] = 200

是這樣的執行的:

  1. y[0] = 100,y現在存儲的內存地址為0x000000,所以修改這個地址下的值:

  2. y = [100],出現了新的對象值,所以要開辟新的堆內存0x000002,創建值,賦值

  3. y[1] = 200,將0x000002地址對應的對象的值進行修改

  4. console.log(y);這個y就是0x000002對應的值[100,200]操作的是私有變量y

fn函數至此執行完畢。

接著執行外面的console.log(x);,此時的x為全局變量對象中的x,對應的地址為0x000000,所以直接進行輸出[100,23]

如果fn執行完之后,繼續執行其他函數,同樣會經歷這樣的流程。形成新的上下文,進棧執行...如果函數非常多,會一直進棧,占內存會越來越大。所以為了優化,瀏覽器會默認做出很多回收機制

結果與總體流程

結果

總體流程圖

其他說明點

js上下文分類

js上下文(哪一個區域下執行)分類

  • 全局上下文EC(G)
  • 函數執行形成的私有上下文
  • 塊級私有上下文

什么是私有變量

私有變量是私有上下文聲明的變量,包含

  1. 形參
  2. 代碼執行的時候聲明的變量var / let / const / function ...
    注意與全局變量區別,沒有直接關系,但是可能會存在一些間接關系,比如下面這段代碼下全局變量x的值是0x000000,通過函數,將0x000000傳給了私有變量y,y也是0x000000
function fn(y) {
    y[0] = 100;
    y = [100];
    y[1] = 200;
    console.log(y);
}
fn(x)

本站僅提供存儲服務,所有內容均由用戶發布,如發現有害或侵權內容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
閉包理解
javascript執行上下文、作用域與閉包(第六篇)
深入理解javascript原型和閉包(15)
深入理解javascript原型和閉包(14)
前端基礎進階(7):函數與函數式編程
前端基礎進階(四):詳細圖解作用域鏈與閉包
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯系客服!

聯系客服

主站蜘蛛池模板: 扎鲁特旗| 肥城市| 芜湖市| 潜江市| 新巴尔虎左旗| 安塞县| 郧西县| 扶沟县| 襄樊市| 成都市| 广饶县| 托克托县| 鄂托克前旗| 谷城县| 灵台县| 三穗县| 赣州市| 安国市| 南安市| 江孜县| 莱西市| 吴忠市| 晋州市| 广水市| 黔江区| 左贡县| 香港| 鹿邑县| 扎鲁特旗| 云安县| 天全县| 北辰区| 永兴县| 福清市| 大冶市| 古交市| 青龙| 城步| 金塔县| 定陶县| 温州市|