您好,登錄后才能下訂單哦!
這篇文章主要介紹了JavaScript中作用域工作模型是什么 ,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
JavaScript內功系列:
this指向詳解,思維腦圖與代碼的結合,讓你一篇搞懂this、call、apply。系列(一)
從原型到原型鏈,修煉JavaScript內功這篇文章真的不能錯過!系列(二)
本文
一、作用域的定義
一張導圖概括本節內容
注意:除了作用域,在此送大家2020最新企業級 Vue3.0/Js/ES6/TS/React/Node等實戰視頻教程,點擊此處免費獲取,小白勿進哦
1.1 常見的解釋
一段程序代碼中所用到的名字并不總是有效,而限定它的可用性的范圍就是這個名字的作用域;
作用域規定了如何查找變量,也就是確定當前執行代碼對變量的訪問權限;
通俗的講作用域就是一套規則,用于確定在何處以及如何查找某個變量的規則
function func(){ var a = 100; console.log(a); // 100}console.log(a) // a is not defined a變量并不是任何地方都可以被找到的
1.2 JavaScript中作用域工作模型
JavaScript 采用是詞法作用域(lexical scoping),也就是靜態作用域:
函數的作用域在函數定義的時候就決定了
與之對應的還有一個動態作用域:
函數的作用域是在函數調用的時候才決定的;
1.3 全局變量和局部變量
根據定義變量的方式又可以分為:
局部變量:只能在函數中訪問,該函數外不可訪問;
定義在函數中的變量
function fn(){ var name = '余光'; console.log(name);}console.log(name); // ?fn(); // ?
全局:任何地方都能訪問到的對象擁有全局作用域。
函數外定義的變量
所有末定義直接賦值的變量自動聲明為擁有全局作用域
var a = 100;console.log('a1-',a);function fn(){ a = 1000; console.log('a2-',a);}console.log('a3-',a);fn();console.log('a4-',a);
注意:在ES6之后又提出了塊級作用域,它們之間的區別我們之后再來討論。
二、理解作用域
根據第一節的描述,我們一一驗證一下
2.1 理解詞法作用域
var value = 1;function foo() { console.log(value);}function bar() { var value = 2; foo();}bar();
我們結合定義去分析:
執行bar
函數,函數內部形成了局部作用域;
聲明value變量,并賦值2
執行foo
函數,函數foo的作用域內沒有value
這個變量,它會向外查找
根據詞法作用域的規則,函數定義時,foo
的外部作用域為全局作用域
打印結果是1
如果是動態作用域的話:結果就是2,不知道你是否想明白了?
2.2 全局變量
var str = '全局變量';function func(){ console.log(str+1); function childFn(){ console.log(str+2); function fn(){ console.log(str+3); }; fn(); }; childFn();}func();// 全局變量1// 全局變量2// 全局變量3
再來分析下面的代碼:
var a = 100;function fn(){ a = 1000; console.log('a1-',a);}console.log('a2-',a);fn();console.log('a3-',a);// a2- 100 // 在當前作用域下查找變量a => 100// a1- 1000 // 函數執行時,全局變量a已經被重新賦值// a3- 1000 // 全局變量a => 1000
2.3 局部作用域
局部作用域一般只在固定的代碼片段內可訪問到,最常見的就是以函數為單位的:
function fn(){ var name="余光"; function childFn(){ console.log(name); } childFn(); // 余光}console.log(name); // name is not defined
三、作用域鏈
3.1 當查找變量的時候都發生了什么?
會先從當前上下文的變量對象中查找;
如果沒有找到,就會從父級(詞法層面上的父級)執行上下文的變量對象中查找;
一直找到全局上下文的變量對象,也就是全局對象;
作用域鏈的頂端就是全局對象;
這樣由多個執行上下文的變量對象構成的鏈表就叫做作用域鏈,從某種意義上很類似原型和原型鏈。
3.2 作用域鏈和原型繼承查找時的區別:
查找一個普通對象的屬性,但是在當前對象和其原型中都找不到時,會返回undefined
查找的屬性在作用域鏈中不存在的話就會拋出ReferenceError
。
3.3 作用域嵌套
既然每一個函數就可以形成一個作用域(詞法作用域
|| 塊級作用域
),那么當然也會存在多個作用域嵌套的情況,他們遵循這樣的查詢規則:
內部作用域有權訪問外部作用域;
外部作用域無法訪問內部作用域;(真是是這樣嗎?)
兄弟作用域不可互相訪問;
在《你不知道的Js》中,希望讀者可以將作用域的嵌套和作用域鏈想象成這樣:
四、思考與總結
4.1 總結
4.2 思考
最后,讓我們看一個《JavaScript權威指南》中的兩段代碼:
var scope = "global scope";function checkscope1(){ var scope = "local scope"; function f(){ return scope; } return f(); // 注意}checkscope1();var scope = "global scope";function checkscope2(){ var scope = "local scope"; function f(){ return scope; } return f;}checkscope2()();
兩段代碼的結果都是"local scope",書中的回答是:JavaScript 函數的執行用到了作用域鏈,這個作用域鏈是在函數定義的時候創建的。嵌套的函數 f() 定義在這個作用域鏈里,其中的變量 scope 一定是局部變量,不管何時何地執行函數 f(),這種綁定在執行 f() 時依然有效。
但是它們內部經歷的事情是一樣的嗎?
感謝你能夠認真閱讀完這篇文章,希望小編分享的“JavaScript中作用域工作模型是什么 ”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。