變量提升(聲)
- 在JS代碼執行之前,浏覽器要先過一遍代碼,把其中 帶 var 和 帶 function 關鍵字内容提前聲明 ;
- 帶 var 是隻聲明(給個預設值 undefined) 不定義
- 帶 function 是聲明加定義
- 因為 用function 關鍵字聲明的函數 ;在變量提升階段已經附好值了,是以 我們可以在JS檔案中的任意位置調用這個函數
- 變量提升 隻會提升 = 号 左邊的部分; 不會提升右邊的部分
- var 一個變量, 相當于 給 window添加一個屬性
- 帶var 會進行變量提升 ,不帶var 的沒有變量提升
- 變量提升 是不看條件成立不成立的; 這個是針對var 來說的
- 針對 function 來說 ,在條件語句中的function聲明;标準浏覽器下是隻聲明,不定義的,在 IE低版本 是既聲明 也 定義的
* var a = 12;
* let a = 12; // 不能重複聲明 能重複定義
* let 沒有變量提升的;
*
* const a = 12;聲明常量用的 不能重複聲明 也不能重複定義
* const 沒有變量提升
// console.log(a,b);
// let c = 13;
var c;//聲明
c = 14;//定義
var a = 12;
var a = 13;
var b = 13;
//let
let e = 13;
e=23;
// console.log(e);
// console.log(a,b);
// function sum() {
// console.log(1)
// }
// sum2();
// var sum2 = function sum3() {
// console.log(2)
// };
// sum2();
d = 2;
// console.log(d);
const aa = 14;
// aa = 13;
// console.log(f,g);
console.log(sum2,sum3);
if(1 > 2){
var f = 12;
function sum2() {
console.log(12)
}
}else {
var g = 14;
function sum3() {
console.log(13);
}
}
console.log(sum2,sum3);
// console.log(f,g);
作用域
- 堆記憶體:存儲的對象鍵值對和函數的函數體
- 棧記憶體:存儲基本資料類型 提供代碼運作的環境
-
作用域: 屬于棧記憶體
代碼執行都會有一個運作環境;我們把這個運作環境成為作用域;
- 私有作用域 ----》函數執行會形成一個私有作用域;提供函數執行的環境
- 全局作用域 ----》 頁面一打開就會形成一個全局作用域;這個作用域是提供整個JS執行環境的
- 私有變量 ----》 在私有作用域下聲明的變量叫做私有變量 (通過 var聲明; 形參)
- 全局變量 ----》 在全局作用域下聲明的變量叫做全局變量(var ; a = 12)
- 作用域鍊 每一個私有作用域都會有他的上級作用域,他的上級作用跟他在哪定義的有關系
上級作用域
函數執行就會形成一個私有的作用域;那這個私有作用域的上級作用域 是誰?
跟這個函數在哪個作用域定義 有關系;在哪個作用域定義的,那麼他的上級作用域就是誰
函數執行的一個過程
函數執行, 先開辟一個私有作用域
然後再進行變量提升 (var function 提前聲明, 先形參指派, 再變量提升)
代碼從上到下 依次執行
// var foo=1;
// function bar(){
// // 不管條件是否成立 都要進行變量提升
// // 這時的 foo 屬于私有變量 給的預設值是 undefined
// if(!foo){
// var foo=10;
// }
// // if(var i =0){
// //
// // }
// console.log(foo);
// }
// bar();
函數的上級作用域 隻跟函數在哪個作用域定義的有關系
跟函數在那裡執行 沒有任何關系
var n=0;
function b(){
n++;
alert(n);
}
function a(){
var n=10;
b();
}
//函數的上級作用域 隻跟函數在哪個作用域定義的有關系
//跟函數在那裡執行 沒有任何關系
b();
a();
alert(n);
擴充題
1.
var n =10;
function outer(){
var n =15;
function inner(){
function center(){
alert(n)
}
center()
}
inner();
}
outer();
結果輸出是15;
第一步:
頁面打開形成全局局作用域,全局作用域裡面有var n=10 和 outer函數進行變量提升,然後代碼自上而下執行n=10;outer函數執行形成一個私有作用域
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL1IDNyUTM1kTMwITMwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
形成私有作用域後,私有作用域裡的var n和inner進行變量提升,給inner函數一個堆記憶體的位址,然後代碼執行,n=15,inner函數執行,依次類推;
直接到center函數執行,到裡面alert(n)執行,因為center函數裡面沒有n變量,沒有傳參,是以查找上一級作用域,他的上一級作用域跟他在哪定義有關系,也就是inner函數,inner裡面沒有n,一直查找上一級作用域到outer函數,裡面有n=15,停止向上查找作用域;
2.
var n =10;
function a(){
var n =10;
function b(){
n++;
alert(n)
}
b();
}
a();
alert(n)
解析: 答案 : 11;0
全局作用域生成,var n=0,和function進行變量提升,給a這個函數一個記憶體位址;,然後函數自上而下執行,a函數執行,形成私有作用域,然後裡面var a =10,進行變量提升,給b函數一個記憶體位址,然後b函數執行,,裡面沒有形參指派和變量提升,n++,b函數裡面沒有n變量,從上一級作用域查找,上一級作用域是a函數,裡面有var n=10;是以b函數執行,n++。alert(n)是11;然後a函數執行完畢,到最後面第二個alert(n),也就是最外面的這個執行,
調用全局作用域,n變量,等于0;
3.
var n =0;
function b(){
n++;
alert(n);
}
function a(){
var n=10;
b();
}
b();
a();
alert(n);
這個a函數執行裡面的b()函數執行,b裡面的n仍從b的上級作用域全局作用域查找n變量,并不是b函數在a函數裡面執行,a函數就是b函數的上級作用域
函數的上級作用域 隻跟函數在哪個作用域定義的有關系
跟函數在那裡執行 沒有任何關系
4.
f = function(){return true};
g = function(){return false};
(function (){
console.log(g);
if(g()&&[]==![]){
f= function f(){return false};
function g(){return true};
}
})();
alert(f());
alert(g())
輸出一個undefined報錯,
全局沒有變量提升,然後代碼自上而下執行,到function自執行函數執行形成私有作用域,私有作用域形成,裡面g函數進行變量提升,隻聲明不定義,是以console.log(g)輸出一個undefined,然後if裡面判斷執行,g不是一個函數,報錯;