大家都知道,JavaScript 代碼是需要在 JavaScript 引擎中運行的。我們在說到 JavaScript 運行的時候,常常會提到執行環境、詞法環境、作用域、執行上下文、閉包等內容。這些概念看起來都差不多,卻好像又不大容易區分清楚,它們分別都在描述什么呢?
這些詞語都是與 JavaScript 引擎執行代碼的過程有關,為了搞清楚這些概念之間的區別,我們可以回顧下 JavaScript 代碼運行過程中的各個階段。
JavaScript 是弱類型語言,在運行時才能確定變量類型。JavaScript 引擎在執行 JavaScript 代碼時,也會從上到下進行詞法分析、語法分析、語義分析等處理,并在代碼解析完成后生成 AST(抽象語法樹),最終根據 AST 生成 CPU 可以執行的機器碼并執行。
這個過程,我們稱之為語法分析階段。除了語法分析階段,JavaScript 引擎在執行代碼時還會進行其他的處理。以 V8 引擎為例,在 V8 引擎中 JavaScript 代碼的運行過程主要分成三個階段。
其中,語法分析階段屬于編譯器通用內容,就不再贅述。前面提到的執行環境、詞法環境、作用域、執行上下文等內容都是在編譯和執行階段中產生的概念。
執行上下文的創建離不開 JavaScript 的運行環境,JavaScript 運行環境包括全局環境、函數環境和eval,其中全局環境和函數環境的創建過程如下:
在不同的運行環境中,變量和函數可訪問的其他數據范圍不同,環境的行為(比如創建和銷毀)也有所區別。而每進入一個不同的運行環境時,JavaScript 都會創建一個新的執行上下文,該過程包括:
由于建立作用域鏈過程中會涉及變量對象的概念,因此我們先來看看變量對象的創建,再看建立作用域鏈和確定 this 的指向。
變量對象(VO)
每個執行上下文都會有一個關聯的變量對象,該對象上會保存這個上下文中定義的所有變量和函數。
在瀏覽器中,全局環境的變量對象是window對象,因此所有的全局變量和函數都是作為window對象的屬性和方法創建的。相應的,在 Node 中全局環境的變量對象則是global對象。
創建VO的過程
創建變量對象將會創建arguments對象(僅函數環境下),同時會檢查當前上下文的函數聲明和變量聲明。
變量聲明和函數聲明的處理過程,便是我們常說的變量提升和函數提升,其中函數聲明提升會優先于變量聲明提升。因為變量提升容易帶來變量在預期外被覆蓋掉的問題,同時還可能導致本應該被銷毀的變量沒有被銷毀等情況。因此 ES6 中引入了let和const關鍵字,從而使 JavaScript 也擁有了塊級作用域。
作用域
在各類編程語言中,作用域分為靜態作用域和動態作用域。JavaScript 采用的是詞法作用域(Lexical Scoping),也就是靜態作用域。詞法作用域中的變量,在編譯過程中會產生一個確定的作用域。
詞法作用域中的變量,在編譯過程中會產生一個確定的作用域,這個作用域即當前的執行上下文,在 ES5 后我們使用詞法環境(Lexical Environment)替代作用域來描述該執行上下文。因此,詞法環境可理解為我們常說的作用域,同樣也指當前的執行上下文(注意,是當前的執行上下文)。
在 JavaScript 中,詞法環境又分為詞法環境(Lexical Environment)和變量環境(Variable Environment)兩種,其中:
也就是說,創建變量過程中會進行函數提升和變量提升,JavaScript 會通過詞法環境來記錄函數和變量聲明。通過使用兩個詞法環境(而不是一個)分別記錄不同的變量聲明內容,JavaScript 實現了支持塊級作用域的同時,不影響原有的變量聲明和函數聲明。
這就是創建變量的過程,它屬于執行上下文創建中的一環。創建變量的過程會產生作用域,作用域也被稱為詞法環境。
作用域鏈,就是將各個作用域通過某種方式連接在一起。作用域就是詞法環境,而詞法環境由兩個成員組成。
通過外部詞法環境的引用,作用域可以層層拓展,建立起從里到外延伸的一條作用域鏈。當某個變量無法在自身詞法環境記錄中找到時,可以根據外部詞法環境引用向外層進行尋找,直到最外層的詞法環境中外部詞法環境引用為null,這便是作用域鏈的變量查詢。
JavaScript 代碼運行過程分為定義期和執行期,前面提到的編譯階段則屬于定義期,代碼示例如下:
function foo() { // 定義全局函數foo
console.dir(bar);
var a = 1;
function bar() { // 在foo函數內部定義函數bar
a = 2;
}
}
console.dir(foo);
foo();
前面我們說到,JavaScript 使用的是靜態作用域,因此函數的作用域在定義期已經決定了。在上面的例子中,全局函數foo創建了一個foo的[[scope]]屬性,包含了全局[[scope]]:
foo[[scope]] = [globalContext];
而當我們執行foo()時,也會分別進入foo函數的定義期和執行期。
在foo函數的定義期時,函數bar的[[scope]]將會包含全局[[scope]]和foo的[[scope]]:
bar[[scope]] = [fooContext, globalContext];
運行上述代碼,我們可以在控制臺看到符合預期的輸出:
可以看到:
也就是說,JavaScript 會通過外部詞法環境引用來創建變量對象的一個作用域鏈,從而保證對執行環境有權訪問的變量和函數的有序訪問。除了創建作用域鏈之外,在這個過程中還會對創建的變量對象做一些處理。
在編譯階段會進行變量對象(VO)的創建,該過程會進行函數聲明和變量聲明,這時候變量的值被初始化為 undefined。在代碼進入執行階段之后,JavaScript 會對變量進行賦值,此時變量對象會轉為活動對象(Active Object,簡稱 AO),轉換后的活動對象才可被訪問,這就是 VO -> AO 的過程,示例如下:
function foo(a) {
var b = 2;
function c() {}
var d = function() {};
}
foo(1);
在執行foo(1)時,首先進入定義期,此時:
AO = {
arguments: {
0: 1,
length: 1
},
a: 1,
b: undefined,
c: reference to function() c() {}
d:undefined
}
前面我們也有提到,進入執行期之后,會執行賦值語句進行賦值,此時變量b和d會被賦值為 2 和函數表達式:
AO = {
arguments: {
0: 1,
length: 1
},
a: 1,
b: 2,
c: reference to function c(){},
d: reference to FunctionExpression "d"
}
這就是 VO -> AO 過程。
實際上在執行的時候,除了 VO 被激活,活動對象還會添加函數執行時傳入的參數和arguments這個特殊對象,因此 AO 和 VO 的關系可以用以下關系來表達:
AO = VO + function parameters + arguments
現在,我們知道作用域鏈是在進入代碼的執行階段時,通過外部詞法環境引用來創建的。總結如下:
通過作用域鏈,我們可以在函數內部可以直接讀取外部以及全局變量,但外部環境是無法訪問內部函數里的變量。示例如下:
function foo() {
var a = 1;
}
foo();
console.log(a); // undefined
我們在全局環境下無法訪問函數foo中的變量a,這是因為全局函數的作用域鏈里,不含有函數foo內的作用域。
如果我們想要訪問內部函數的變量,可以通過函數foo中的函數bar返回變量a,并將函數bar返回,這樣我們在全局環境中也可以通過調用函數foo返回的函數bar,來訪問變量a:
function foo() {
var a = 1;
function bar() {
return a;
}
return bar;
}
var b = foo();
console.log(b()); // 1
當函數執行結束之后,執行期上下文將被銷毀,其中包括作用域鏈和激活對象。
在上面的實例中;當b()執行時,foo函數上下文包括作用域都已經被銷毀了,但是foo作用域下的a依然可以被訪問到;這是因為bar函數引用了foo函數變量對象中的值,此時即使創建bar函數的foo函數執行上下文被銷毀了,但它的變量對象依然會保留在 JavaScript 內存中,bar函數依然可以通過bar函數的作用域鏈找到它,并進行訪問。這就是閉包;
閉包使得我們可以從外部讀取局部變量,常見的用途包括:
注意,在使用閉包的時候,需要及時清理不再使用到的變量,否則可能導致內存泄漏問題。
在 JavaScript 中,this指向執行當前代碼對象的所有者,可簡單理解為this指向最后調用當前代碼的那個對象。
根據 JavaScript 中函數的調用方式不同,this的指向分為以下情況。
可以看到,this在不同的情況下會有不同的指向,在 ES6 箭頭函數還沒出現之前,為了能正確獲取某個運行環境下this對象,我們常常會使用以下代碼:
var that = this;
var self = this;
這樣的代碼將變量分配給this,便于使用。但是降低了代碼可讀性,不推薦使用,通過正確使用箭頭函數,我們可以更好地管理作用域。
今天我們了解了 JavaScript 代碼的運行過程,該過程分為語法分析階段、編譯階段、執行階段三個階段。
在編譯階段,JavaScript會進行執行上下文的創建,在執行階段,變量對象(VO)會被激活為活動對象(AO),變量會進行賦值,此時活動對象才可被訪問。在執行結束之后,作用域鏈和活動對象均被銷毀,使用閉包可使活動對象依然被保留在內存中。這就是 JavaScript 代碼的運行過程。
錄
Web 開發正在成為 IT 中最受歡迎的領域之一,毫無疑問,JavaScript 和 Python 都是 Web 開發人員中非常流行的編程語言。這兩種編程語言都有自己的優點,這使它們成為開發人員的熱門選擇。
然而,Python 和 JavaScript 的比較一直是開發者社區的熱門討論。它經常會產生這樣的問題:python 比 javascript 難嗎?python比javascript好嗎?python和javascript有什么區別?javascript在Web開發中的用途是什么?等等等等。繼續閱讀本文,因為本文簡要回答了所有這些問題,但在討論這些編程語言在 Web 開發中的比較之前,了解什么是 Python 和 JavaScript 至關重要。
Python 是當今最好和最強大的編程語言之一。它用途廣泛,是大多數科學應用的必備工具。但是,它是一種通用編程語言,支持不同的編程范式。
這種編程廣泛用于科學領域,包括數據科學、人工智能、計算機視覺 (CV)、DIP(數字圖像處理)、自然語言處理和 Web 開發。Python 的語法非常簡單。這就是為什么很多人認為 python 比 javaScript 好得多的原因。
在 web 開發的背景下,有一個流行的問題:python 是用于前端還是后端?答案是python主要用于后端。這是我們可以將其功能和能力與 JavaScript 進行比較的地方。但是,需要注意的是,Python 不僅限于后端開發,還可以在一些附加工具的幫助下用于前端開發。
雖然 Python 是后端開發的絕佳選擇,但 JavaScript 是首選,并且通常被稱為 Web 應用程序前端開發的編程語言。
在這里了解后端和前端開發之間的區別很重要。Web 應用程序的后端是用戶無法訪問且用戶不直接與其交互的部分。它包含 Web 應用程序的所有業務邏輯和服務器端編程。
另一方面,Web 應用程序的前端是最終用戶與之交互的部分。這是用戶可以訪問的應用程序的一部分。即使您正在與移動應用程序交互,您也很可能正在與 React.js(一個 JavaScript 框架)進行交互,它能夠開發能夠適應不同平臺的應用程序。
現在,由于我們已經清楚地了解了 JavaScript 和 Python,我們可以更深入地挖掘它們的差異化因素。
我們可以根據不同的理由來區分這兩種編程語言。python 和 JavaScript 都有各自的優缺點。因此,讓我們立即開始吧。
首先,重要的是要注意開發人員社區對這兩種編程語言的看法。確定開發人員選擇的最佳矩陣是評估這些編程語言的流行程度。
根據Stack Overflow 的 2020 年開發者調查,JavaScript 在最常用的編程語言列表中名列前茅。根據調查的詳細信息,幾乎 69.7% 的開發社區使用 JavaScript。相比之下,Python 的普及率在 41.7% 的開發者中。
JavaScript 流行的一個原因是它的工作可以廣泛使用。此外,它不僅可用于 Web 開發,而且 JavaScript 還可用于移動應用程序開發,這使其成為開發社區中的熱門選擇。
性能是開發網站時要牢記的最重要因素之一。如果應用程序不夠高效,它幾乎是無用的。這就是新的編程語言試圖灌輸盡可能多的效率和優化的原因。
然而,這并不容易,而是一項非常棘手的任務。這也取決于用于開發的編程語言。因為每種編程語言都有自己的內置規則和方法來提高效率。
Web 應用程序的速度取決于 Web 應用程序中代碼的執行速度。構建 JavaScript 的目的是在 Web 瀏覽器上快速運行。這就是 Facebook、Google、Amazon 等應用程序使用 JavaScript 的原因。
如果將 Python Web 應用程序與 Node.js Web 應用程序進行比較,Node.js 肯定會勝過 Python。因為據專家介紹,Python 在單個流中處理請求,但 JavaScript 可以利用其先進的多線程功能一次處理多個請求。
對于一個人來說,Web 應用程序的可擴展性就像氧氣一樣是生存所必需的。考慮一個應用程序,該應用程序響應速度快、交互性強,并提供非常需要的服務。但是,它無法同時處理大量請求。這將導致網絡流量下降,因為如果用戶打開一個網站并且它沒有按需要響應或經常崩潰,但用戶最終也會尋找其他一些快速的替代方案。
因此,應用程序的可擴展性非常重要。因為可伸縮性允許應用程序一次處理大量的流量和請求。為了支持可擴展性,多線程是一個非常可行的解決方案。但是 Python 不支持多線程,因為它適用于單線程系統。相反,它使用全局解釋器鎖來一次處理多個請求。
相反,Node.js 純粹是為了支持異步編程而開發的。因此,JavaScript 在 Web 應用程序可擴展性方面表現出色。但是,Python 也可以通過上述方式實現可擴展性。
內存管理是另一個需要考慮的重要方面。如果一種編程語言不能有效地管理內存,將直接影響網站的優化。
在 Python 中,所有變量和數據結構都收集在一個堆中。Python 也有它的內部內存管理器來確保對這個堆的管理。
但是,JavaScript 使用一種稱為 GC(垃圾收集器)的自動內存管理工具。但是,GC 的管理工作在一個近似算法上,因為它無法知道某個內存位置是否無用。
編程語言的范圍定義了它的多功能性。如果我們談論 Python 的應用程序或用例,我們就會知道 Python 用于后端的 Web 開發。它在軟件開發、計算和腳本系統中也非常有用。它在數據科學和機器學習中非常流行。
相比之下,JavaScript 也支持所有這些類型的軟件開發。JavaScript 相對于 python 的最大優勢在于,它不僅是一種前端語言,而且在開發應用程序的服務器端邏輯時也能工作得非常好。此外,JavaScrip 還用于開發移動應用程序,目前 Python 不支持。React.js 是流行的移動應用程序開發框架之一。
根據上面進行的討論,很明顯這兩種語言都有自己的優缺點。幾乎不可能質疑 Python 是否會取代 JavaScript,反之亦然。
對于 JavaScript 和 Python,開發人員的選擇將基于所考慮平臺的要求。例如,當語言的設計至關重要時,Python 是您的選擇。如果需要移動開發和高度響應的網站,那么 JavaScript 是您的選擇。
更全面地說,如果所需的應用程序必須具有可擴展性和高效性,那么 JavaScript 是正確的選擇。而如果網站后臺非常復雜,可讀性好,又要求編程簡單,可以選擇Python。
關于是選擇Python還是前端,我的建議是這樣的,在學歷這塊,目前Python和前端這塊招聘學歷最低需求都是大專,所以這塊問題不大,其次你最想要知道的就是選擇Python還是前端,下面我從市場發展前景以及薪資待遇這兩方面具體的分析一下:
先說下Python,Python這個編程語言在近兩年比較火,之所以比較火,在很大程度上面要歸根于培訓機構,很多培訓機構借助于人工智能的熱潮從而進行炒作,以此招生盈利。
現在我認為Python主要的三個方向,web開發,網絡爬蟲,人工智能。
如果你選擇做web開發,我更建議你選擇Javaweb,Javaweb的發展以及提升空間更大。
其次是網絡爬蟲,網絡爬蟲我現在不建議你學,因為現在這個方向現在這方面的崗位比較少。
其次就是人工智能,這個方向就更不建議你考慮了,因為門檻比較高,最低學歷需求都是碩士以上,因為涉及到很多算法方面的東西。而且現在Python這個語言的話,發展得不是很完善,相當于你現在學了出來,只能在一線城市找到合適的崗位工作,二線三線城市基本上,沒有這方面的崗位。
如果你選擇學習Python的話,這三個方向你最終只能選擇Python web開發,剛學完技術出來,你可以考慮去一線城市發展,提升一下自己的閱歷,技術,經驗等等,但是萬事都需要從長遠考慮,目前所在的城市以后是否會具備這方面的崗位。
我們來看下目前Python的薪資待遇水平:
目前在北京等這樣的一線城市Python崗位的薪資待遇水平在20k左右(有一定的水分),當然這是具備一定開發經驗的,一般剛學完Python技術出來的,只要能找到相關的工作,薪資待遇大約都在5-7k左右。其次我在職友集上面搜索一下一些二線城市Python崗位,基本上沒有相關的崗位招聘。基本上這個就是目前Python的一個市場行情。
下面我們來說下前端,web前端這個語言在國內流行了很多年的時間,可以說現在無論你是在一線城市,還是二線三線城市,你學了前端,都可以找到合適的崗位工作。
雖說現在前端的基數大,但是真正懂前端技術,會寫代碼的前端非常的少。
從現在的大企業來講,他是不要那種單純的只會去做機械性勞動的前端。這種競爭就比較少,所以在前端這個領域里面來看,機會非常的多。所以你們一定要成為真正的前端,而不是就成為只會切個圖,做機械性勞動的前端。
我們來看下目前前端崗位的薪資待遇水平:
目前在北京等這樣的一線城市,前端方面的薪資待遇在18k左右,當然這也是具備一定開發經驗的前端,屬于比較正常的薪資待遇水平。
剛學完前端技術出來的初級前端一般薪資待遇在5-7k左右。
這里給你提供一個web前端的系統學習路線:
web前端基礎部分的HTML,CSS都比較簡單,比較難的部分就是后面JavaScript部分。
總的來說,非要我建議的話我更建議你學習web前端。因為前端這個工作更加穩定,不管是二線三線都比較好找工作,而且相比起Python,前端更容易掌握。
以上就是關于PYthon和前端HTML5之間的區別,大家可以根據自身情況考慮是該選擇哪個方面。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。