作用域
JS中有兩種作用域:全域作用域|局部作用域
#栗子1
console.log(name); //undefined var name = '波妞'; var like = '宗介' console.log(name); //波妞 function fun(){ console.log(name); //波妞 console.log(eat) //ReferenceError: eat is not defined (function(){ console.log(like) //宗介 var eat = '肉' })() } fun();
【相關課程推薦:JavaScript影片教學】
1. name定義在全域,在全域可以存取到,所以(2)列印能夠正確列印;
2. 在函數fun中,如果沒有定義name屬性,那麼會到它的父作用域去找,所以(3) 也能正確列印。
3. 內部環境可以透過作用域鏈存取所有外部環境,但外部環境無法存取內部環境的任何變數和函數。類似單向透明,這就是作用域鏈,所以 (4) 不行而 (5) 可以。
那麼問題來了,為什麼第一個列印是"undefined",而不是"ReferenceError: name is not defined"。原理簡單的說就是JS的變數提升
變數提升:JS在解析程式碼時,會將所有的宣告提前到所在作用域的最前面
栗子2
console.log(name); //undefined var name = '波妞'; console.log(name); //波妞 function fun(){ console.log(name) //undefined console.log(like) //undefined var name = '大西瓜'; var like = '宗介' } fun();
#相當於
var name; console.log(name); //undefined name = '波妞'; console.log(name); //波妞 function fun(){ var name; var like; console.log(name) //undefined console.log(like) //undefined name = '大西瓜'; like = '宗介' console.log(name) //大西瓜 console.log(like) //宗介 } fun();
注意:是提前到目前作用域的最前面
栗子3
printName(); //printName is not a function var printName = function(){ console.log('波妞') } printName(); //波妞
#相當於
var printName; printName(); //printName is not a function printName = function(){ console.log('波妞') } printName(); //波妞
這樣就好理解了,函數表達式在宣告的時候還只是個變數
栗子4
{ var name = '波妞'; } console.log(name) //波妞 (function(){ var name = '波妞'; })() console.log(name) //ReferenceError: name is not defined { let name = '波妞'; } console.log(name) //ReferenceError: name is not defined
從上面的栗子可以看出,不可以草率的認為JS中var聲明的變數的作用範圍就是大括號的起止範圍,ES5並沒有區塊級作用域,實質是函數作用域;ES6中有了let、const定義後,才有了區塊級作用域。
栗子5
function p1() { console.log(1); } function p2() { console.log(2); } (function () { if (false) { function p1() { console.log(3); } }else{ function p2(){ console.log(4) } } p2(); p1() })(); //4 //TypeError: print is not a function
這是一個非常經典的栗子,宣告提前了,但是因為判斷條件為否,所以沒有執行函數體。所以會出現"TypeError: print is not a function"。 while,switch,for同理
閉包
函數與對其狀態即詞法環境(lexical environment)的引用共同構成閉包(closure )。也就是說,閉包可以讓你從內部函數存取外部函數作用域。在JavaScript中,函數在每次建立時產生閉包。
上面的定義來自MDN,簡單講,閉包就是指有權存取另一個函數作用域中變數的函數。
● 閉包的關鍵在於:外部函數呼叫之後其變數物件本來應該被銷毀,但閉包的存在使我們仍然可以存取外部函數的變數物件. ,
//举个例子 function makeFunc() { var name = "波妞"; function displayName() { console.log(name); } return displayName; } var myFunc = makeFunc(); myFunc();
JavaScript中的函數會形成閉包。閉包是由函數以及創建該函數的詞法環境組合而成。這個環境包含了這個閉包建立時所能存取的所有局部變數
在範例中,myFunc 是執行makeFunc 時所建立的displayName 函式實例的引用,而displayName 實例仍可存取其詞法作用域中的變量,即可以存取name 。由此,當 myFunc 被呼叫時,name 仍可被訪問,其值 '波妞' 就被傳遞到console.log中。 建立閉包最常見方式,就是在一個函數內部建立另一個函數
#● 通常,函數的作用域及其所有變數都會在函數執行結束後被銷毀。但是,在創建了一個閉包以後,這個函數的作用域就會一直保存到閉包不存在為止
//例二 function makeAdder(x) { return function(y) { return x + y; }; } var add5 = makeAdder(5); var add10 = makeAdder(10); console.log(add5(2)); // 7 console.log(add10(2)); // 12 //释放对闭包的引用 add5 = null; add10 = null;
從本質上講,makeAdder 是一個函數工廠— 他創建了將指定的值和它的參數相加求和的函數。在上面的範例中,我們使用函數工廠建立了兩個新函數 — 一個將其參數和 5 求和,另一個和 10 求和。
add5 和 add10 都是閉包。它們共享相同的函數定義,但是保存了不同的詞法環境。在 add5 的環境中,x 為 5。而在 add10 中,x 則為 10。
閉包的作用域鏈包含它自己的作用域,以及包含它的函數的作用域和全域作用域。
● 閉套件只能取得包含函數中的任何變數的最後一個值
//栗子1 function arrFun1(){ var arr = []; for(var i = 0 ; i < 10 ; i++){ arr[i] = function(){ return i } } return arr } console.log(arrFun1()[9]()); //10 console.log(arrFun1()[1]()); //10 //栗子2 function arrFun2(){ var arr = []; for(var i = 0 ; i < 10 ; i++){ arr[i] = function(num){ return function(){ return num }; }(i) } return arr } console.log(arrFun2()[9]()); //9 console.log(arrFun2()[1]()); //1
栗子1 中,arr陣列中包含10個匿名函數,每個函數都可以存取外部的變數i , arrFun1 執行後,其作用域被銷毀,但它的變數依然存在記憶體中,能被循環中的匿名函數訪問,這是的i 為10;
栗子2 中,arr數組中有是個匿名函數,其匿名函數內還有匿名函數,最內層匿名函數訪問的num 被上一級匿名函數保存在了內存中,所以可以訪問到每次的i 的值。
本文來自 js教學 欄目,歡迎學習!
以上是js作用域和閉包詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Python和JavaScript的主要區別在於類型系統和應用場景。 1.Python使用動態類型,適合科學計算和數據分析。 2.JavaScript採用弱類型,廣泛用於前端和全棧開發。兩者在異步編程和性能優化上各有優勢,選擇時應根據項目需求決定。

選擇Python還是JavaScript取決於項目類型:1)數據科學和自動化任務選擇Python;2)前端和全棧開發選擇JavaScript。 Python因其在數據處理和自動化方面的強大庫而備受青睞,而JavaScript則因其在網頁交互和全棧開發中的優勢而不可或缺。

Python和JavaScript各有優勢,選擇取決於項目需求和個人偏好。 1.Python易學,語法簡潔,適用於數據科學和後端開發,但執行速度較慢。 2.JavaScript在前端開發中無處不在,異步編程能力強,Node.js使其適用於全棧開發,但語法可能複雜且易出錯。

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

記事本++7.3.1
好用且免費的程式碼編輯器

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

禪工作室 13.0.1
強大的PHP整合開發環境