深入理解javascript原型和閉包筆記

讀完 深入理解javascript原型和閉包 的一些摘錄。

javascript原型和閉包

一切都是對象

四種(undefined, number, string, boolean)屬於簡單的值類型,不是對象。剩下的幾種情況——函數、數組、對象、null、new Number(10)都是對象。他們都是引用類型。

值類型的類型判斷用typeof,引用類型的類型判斷用instanceof。

一切(引用類型)都是對象,對象是屬性的集合

函數和對象

對象都是通過函數創建的

prototype原型和隱式原型

每個函數都有一個屬性叫做prototype,這個prototype的屬性值是一個對象(屬性的集合,再次強調!),默認的只有一個叫做constructor的屬性,指向這個函數本身。

爲每個對象都有一個隱藏的屬性——“proto”,這個屬性引用了創建這個對象的函數的prototype。即:fn.proto === Fn.prototype

每個函數function都有一個prototype,即原型。每個對象都有一個__proto__,可成爲隱式原型

Object.prototype確實一個特例——它的__proto__指向的是null

Instanceof

Instanceof運算符的第一個變量是一個對象,暫時稱爲A;第二個變量一般是一個函數,暫時稱爲B。
Instanceof的判斷隊則是:沿着A的__proto__這條線來找,同時沿着B的prototype這條線來找,如果兩條線能找到同一個引用,即同一個對象,那麼就返回true。如果找到終點還未重合,則返回false。

instanceof: 一個對象在其原型鏈中是否存在一個構造函數prototype屬性
在這裏插入圖片描述

原型鏈和繼承

訪問一個對象的屬性時,先在基本屬性中查找,如果沒有,再沿着__proto__這條鏈向上找,這就是原型鏈。

實際應用中如何區分一個屬性到底是基本的還是從原型中找到的呢?hasOwnProperty

每個函數都有call,apply方法,都有length,arguments,caller等屬性。爲什麼每個函數都有?這肯定是“繼承”的。函數由Function函數創建,因此繼承的Function.prototype中的方法。那怎麼還有hasOwnProperty呢?——那是Function.prototype繼承自Object.prototype的方法。

靈活性:可以在prototype上修改和創建方法

執行上下文和上下文環境

在一段js代碼拿過來真正一句一句運行之前,瀏覽器已經做了一些“準備工作”,其中就包括對變量的聲明,而不是賦值。變量賦值是在賦值語句執行的時候進行的。
在這裏插入圖片描述

我們總結一下,在“準備工作”中完成了哪些工作:

  • 變量、函數表達式——變量聲明,默認賦值爲undefined;
  • this——賦值;
  • 函數聲明——賦值;
    這三種數據的準備情況我們稱之爲“執行上下文”或者“執行上下文環境”。

this指向 構造函數 和 被誰調用

執行全局代碼時,會產生一個執行上下文環境,每次調用函數都又會產生執行上下文環境。當函數調用完成時,這個上下文環境以及其中的數據都會被消除,再重新回到全局上下文環境。處於活動狀態的執行上下文環境只有一個。其實這是一個壓棧出棧的過程——執行上下文棧。
在這裏插入圖片描述

作用域

javascript除了全局作用域之外,只有函數可以創建的作用域。作用域最大的用處就是隔離變量,不同作用域下同名變量不會有衝突。

作用域只是一個“地盤”,一個抽象的概念,其中沒有變量。要通過作用域對應的執行上下文環境來獲取變量的值。同一個作用域下,不同的調用會產生不同的執行上下文環境,繼而產生不同的變量的值。所以,作用域中變量的值是在執行過程中產生的確定的,而作用域卻是在函數創建時就確定了。所以,如果要查找一個作用域下某個變量的值,就需要找到這個作用域對應的執行上下文環境,再在其中尋找變量的值。

在這裏插入圖片描述

作用域鏈

一般情況下,變量取值到 創建 這個變量 的函數的作用域中取值。但是如果在當前作用域中沒有查到值,就會向上級作用域去查,直到查到全局作用域,這麼一個查找過程形成的鏈條就叫做作用域鏈。
在這裏插入圖片描述

閉包

閉包:閉包是指有權訪問另一個函數作用域中的變量的函數,只有兩種情況——函數作爲返回值,函數作爲參數傳遞

執行完第17行,fn()調用完成。按理說應該銷燬掉fn()的執行上下文環境,但是這裏不能這麼做。注意,重點來了:因爲執行fn()時,返回的是一個函數。函數的特別之處在於可以創建一個獨立的作用域。而正巧合的是,返回的這個函數體中,還有一個自由變量max要引用fn作用域下的fn()上下文環境中的max。因此,這個max不能被銷燬,銷燬了之後bar函數中的max就找不到值了。

因此,這裏的fn()上下文環境不能被銷燬,還依然存在與執行上下文棧中。

——即,執行到第18行時,全局上下文環境將變爲活動狀態,但是fn()上下文環境依然會在執行上下文棧中。另外,執行完第18行,全局上下文環境中的max被賦值爲100。
在這裏插入圖片描述

執行到第20行,執行f1(15),即執行bar(15),創建bar(15)上下文環境,並將其設置爲活動狀態。

在這裏插入圖片描述
執行bar(15)時,max是自由變量,需要向創建bar函數的作用域中查找,找到了max的值爲10。

這裏的重點就在於,創建bar函數是在執行fn()時創建的。fn()早就執行結束了,但是fn()執行上下文環境還存在與棧中,因此bar(15)時,max可以查找到。如果fn()上下文環境銷燬了,那麼max就找不到了。

執行完20行就是上下文環境的銷燬過程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章