摘要:全局作用域在任何函數塊或模塊范圍之外定義的變量具有全局作用域。的局部函數作用域是函數的詞法作用域。作用域鏈每個作用域都有一個指向父作用域的鏈接。當使用變量時,會向下查看作用域鏈,直到它找到所請求的變量或者到達全局作用域即作用域鏈的末尾。
一網打盡 JavaScript 的作用域
翻譯:瘋狂的技術宅
https://medium.freecodecamp.o...??-javascript-cbd957022652
本文首發微信公眾號:jingchengyideng
歡迎關注,每天都給你推送新鮮的前端技術文章
作用域決定了變量的生命周期和可見性,變量在作用域范圍之外是不可見的。
JavaScript 的作用域包括:模塊作用域,函數作用域,塊作用域,詞法作用域和全局作用域。
全局作用域在任何函數、塊或模塊范圍之外定義的變量具有全局作用域。可以在程序的任意位置訪問全局變量。
當啟用模塊系統時,創建全局變量會變得困難,但仍然可以做到這一點。可以在 HTML 中定義一個變量,這個變量需要在函數之外聲明,這樣就可以創建一個全局變量:
console.log(GLOBAL_DATA);
當沒有模塊系統時,創建全局變量會容易很多。在任何文件中的函數外聲明的變量都是全局變量。
全局變量貫穿于程序的整個生命周期。
另一種創建全局變量的方法是在程序的任意位置使用 window 全局對象:
window.GLOBAL_DATA = { value: 1 };
這樣 GLOBAL_DATA 變量會隨處可見。
console.log(GLOBAL_DATA)
不過你也知道這種做法是不好的。
模塊作用域如果不啟用模塊,在所有函數之外聲明的變量是全局變量。在模塊中,在函數外部聲明的變量都是隱藏的,除非顯式導出,否則不可用于其他模塊。
導出使函數或對象可用于其他模塊。在這個例子中,我從模塊文件 sequence.js 中導出了一個函數:
// in sequence.js export { sequence, toList, take };
當前模塊可以通過導入來使用其他模塊的函數或對象成。
import { sequence, toList, toList } from "./sequence";
在某種程度上,我們可以認為模塊是一個自動執行的函數,它將 import 的數據作為輸入,然后返回 export 的數據。
函數作用域函數作用域意味著在函數中定義的參數和變量在函數內的任何位置都可見,但是在函數外部不可見。
下面是一個自動執行的函數,被稱為IIFE。
(function autoexecute() { let x = 1; })(); console.log(x); //Uncaught ReferenceError: x is not defined
IIFE 的意思是立即調用函數表達式,是一個在定義后立即運行的函數。
用 var 聲明的變量只有函數作用域。更重要的是,用 var 聲明的變量被提升到其作用域的頂部。通過這種方式,可以在聲明之前訪問它們。看看下面的代碼:
function doSomething(){ console.log(x); var x = 1; } doSomething(); //undefined
這種事不會發生在 let 中。用 let 聲明的變量只能在定義后訪問。
function doSomething(){ console.log(x); let x = 1; } doSomething(); //Uncaught ReferenceError: x is not defined
用 var 聲明的變量可以在同一作用域下多次重新聲明:
function doSomething(){ var x = 1 var x = 2; console.log(x); } doSomething();
用 let 或 const 聲明的變量不能在同一作用域內重新聲明:
function doSomething(){ let x = 1 let x = 2; } //Uncaught SyntaxError: Identifier "x" has already been declared
也許我們可以不必關心這一點,因為 var 已經開始變得過時了。
塊作用域塊作用域用花括號定義。它由 { 和 } 分隔。
用 let 和 const 聲明的變量可以受到塊作用域的約束,只能在定義它們的塊中訪問。
思考下面這段關于 let 塊范圍的代碼:
let x = 1; { let x = 2; } console.log(x); //1
相反,var 聲明不受塊作用域的約束:
var x = 1; { var x = 2; } console.log(x); //2
另一個常見問題是在循環中使用類似 setTimeout() 的異步操作。下面的循環代碼將顯示五次數字 5。
(function run(){ for(var i=0; i<5; i++){ setTimeout(function logValue(){ console.log(i); //5 }, 100); } })();
帶有 let 聲明的 for 循環語句在每次循環都會創建一個新的變量并設置到塊作用域。下一段循環代碼將會顯示 0 1 2 3 4 5。
(function run(){ for(let i=0; i<5; i++){ setTimeout(function log(){ console.log(i); //0 1 2 3 4 }, 100); } })();詞法作用域
詞法作用域是內部函數訪問定義它的外部作用域的能力。
看一下這段代碼:
(function autorun(){ let x = 1; function log(){ console.log(x); }; function run(fn){ let x = 100; fn(); } run(log);//1 })();
log 函數是一個閉包。它從父函數 autorun() 引用 x 變量,而不是 run() 函數中的 x 變量。
閉包函數可以訪問創建它的作用域,而不是它自己的作用域。
autorun() 的局部函數作用域是 log() 函數的詞法作用域。
作用域鏈每個作用域都有一個指向父作用域的鏈接。當使用變量時,JavaScript 會向下查看作用域鏈,直到它找到所請求的變量或者到達全局作用域(即作用域鏈的末尾)。
看下面這個例子:
let x0 = 0; (function autorun1(){ let x1 = 1; (function autorun2(){ let x2 = 2; (function autorun3(){ let x3 = 3; console.log(x0 + " " + x1 + " " + x2 + " " + x3);//0 1 2 3 })(); })(); })();
內部函數 autorun3() 可以訪問本地 x3 變量。還可以從外部函數訪問變量 x1 和 x2 和全局變量 x0 。
如果找不到變量,它將在嚴格模式下返回錯誤。
"use strict"; x = 1; console.log(x) //Uncaught ReferenceError: x is not defined
非嚴格模式也被稱為“草率模式”,它會草率的創建一個全局變量。
x = 1; console.log(x); //1總結
在全局作用域中定義的變量可在程序的任何位置使用。
在模塊中,在函數外部聲明的變量都是隱藏的,除非被顯式導出,否則不可用于其他模塊。
函數作用域意味著函數中定義的參數和變量在函數的任意位置都可見
用 let 和 const 聲明的變量具有塊作用域。 var 沒有塊作用域。
本文首發微信公眾號:jingchengyideng 歡迎掃描二維碼關注公眾號,每天都給你推送新鮮的前端技術文章 歡迎繼續閱讀本專欄其它高贊文章:12個令人驚嘆的CSS實驗項目
世界頂級公司的前端面試都問些什么
CSS Flexbox 可視化手冊
過節很無聊?還是用 JavaScript 寫一個腦力小游戲吧!
從設計者的角度看 React
CSS粘性定位是怎樣工作的
一步步教你用HTML5 SVG實現動畫效果
程序員30歲前月薪達不到30K,該何去何從
7個開放式的前端面試題
React 教程:快速上手指南
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/109341.html
摘要:使用的好處知乎的回答不用自己組裝,拿來就用。統一配置,便于修改。 前言 只有光頭才能變強 回顧前面: 給女朋友講解什么是代理模式 包裝模式就是這么簡單啦 單例模式你會幾種寫法? 工廠模式理解了沒有? 在刷Spring書籍的時候花了點時間去學習了單例模式和工廠模式,總的來說還是非常值得的! 本來想的是刷完《Spring 實戰 (第4版)》和《精通Spring4.x 企業應用開發實戰》...
摘要:我在面試前針對基礎也花了不少的時間,期間也將自己寫過的博文粗略地刷了一遍,同時也在網上找了不少比較好的資料部分是沒看完的。看面試題也是校驗自己是否真正理解了這個知識點,也很有可能會有新的收獲。 一、前言 只有光頭才能變強 回顧前面: 廣州三本找Java實習經歷 上一篇寫了自己面試的經歷和一些在面試的時候遇到的題目(筆試題和面試題)。 我在面試前針對Java基礎也花了不少的時間,期間也將...
摘要:先說遍歷,很簡單,如下行左右代碼就足夠遍歷一個對象了遇到普通數據屬性,直接處理,遇到對象,遍歷屬性之后遞歸進去處理屬性,遇到數組,遞歸進去處理數組元素。這樣改進之后我就不需要對數組元素進行響應式處理,只是遇到數組的時候把數組的方法變異即可。 用了Vue很久了,最近決定系統性的看看Vue的源碼,相信看源碼的同學不在少數,但是看的時候卻發現挺有難度,Vue雖然足夠精簡,但是怎么說現在也有1...
摘要:摘要第二屆研發效能嘉年華峰會,云效邀請天貓技術部高級技術專家吳建和枯木帶來題為天貓雙項目組織協同的演講。所有的這些雙項目的組織形式會依賴集團已有的產品線,例如資金平臺支付交易鏈路物流等等這類平臺,所有這些項目都會涉及到比較大的組織上的協同。 摘要: 2018第二屆研發效能嘉年華峰會,云效邀請天貓技術部高級技術專家吳建和(枯木)帶來題為天貓雙11項目組織協同的演講。主要內容是從四個方面進...
摘要:另外,這些中的每一個都是純函數,有返回值。例如,如果要計算整數列表的累積乘,或者求和等等基礎語法參數是連續作用于每一個元素的方法,新的參數為上一次執行的結果,為被過濾的可迭代序列返回值最終的返回結果在中,是一個內置函數。 簡潔的內置函數 大家好,我又回來了,今天我想和大家分享的是Python非常重要的幾個內置函數:map,filter,reduce, zip。它們都是處理序列的便捷函數...
閱讀 2958·2021-11-24 09:39
閱讀 2870·2021-09-29 09:34
閱讀 3563·2021-09-24 10:23
閱讀 1746·2021-09-22 15:41
閱讀 1702·2019-08-30 15:55
閱讀 3517·2019-08-30 13:58
閱讀 2624·2019-08-30 13:11
閱讀 1672·2019-08-29 12:31