什么是作用域
當(dāng)前的執(zhí)行上下文券躁。值和表達(dá)式在其中 "可見" 或可被訪問到的上下文监徘。如果一個變量或者其他表達(dá)式不 "在當(dāng)前的作用域中",那么它就是不可用的音榜。 作用域也可以根據(jù)代碼層次分層辟灰,以便子作用域可以訪問父作用域哈垢,通常是指沿著鏈?zhǔn)降淖饔糜蜴湶檎依蛋疲荒軓母缸饔糜蛞米幼饔糜蛑械淖兞亢鸵谩?/p>
當(dāng)然,一個 Function 將生成一個閉包(通常是返回一個函數(shù)引用)封恰,這個函數(shù)引用從外部作用域(在當(dāng)前環(huán)境下)可以訪問閉包內(nèi)部的作用域
- ECMAScript5 只有全局作用域和函數(shù)作用域麻养,ECMAScript6 之后才有塊級作用域(let 、const)
全局作用域
定義的變量或函數(shù)在整個JavaScript程序中诺舔,都是可見的
var name = 'zyc'; // 全局變量
// 全局函數(shù)
function foo() {
console.log(name); //使用全局變量
}
foo(); // 運(yùn)行打颖畈: zyc
//全局函數(shù)
function bar(){
//嵌套函數(shù)
function getAge(){
console.log(name); //使用全局變量
}
getAge(); //運(yùn)行打印:zyc
foo(); //運(yùn)行打拥挽:zyc
}
bar();
console.log(name) //打有碜颉:zyc
函數(shù)作用域
定義在函數(shù)中的參數(shù)和變量或嵌套函數(shù)在函數(shù)外部是不可見的
console.log(age); //報錯 Uncaught ReferenceError: age is not defined
getAge(); //報錯 Uncaught ReferenceError: getAge is not defined
//全局函數(shù)
function bar(){
var age= 10;
//嵌套函數(shù)
function getAge(){
console.log(age);
}
getAge(); //運(yùn)行打印:10
}
bar();
getAge(); //報錯 Uncaught ReferenceError: getAge is not defined
console.log(age); //報錯 Uncaught ReferenceError: age is not defined
塊級作用域
任何一對花括號 {} 中的語句集都屬于一個塊褥赊,在這之中定義的所有變量在代碼塊外都是不可見的糕档,我們稱之為塊級作用域。
function bar() {
var name = "zxy";
{
let age = 10;
var kk = 'kk'
}
console.log(name); //打印輸出 zxy
console.log(kk); //打印輸出 kk
console.log(age); //報錯 Uncaught ReferenceError: age is not defined
}
bar();
變量與聲明提升
- var 關(guān)鍵字定義的變量可以在使用后聲明拌喉,也就是變量可以先使用再聲明(聲明提升)
- 使用 var 關(guān)鍵字聲明的變量在任何地方都可以修改
- let 速那、const關(guān)鍵字定義的變量則不可以在使用后聲明,也就是變量需要先聲明再使用尿背。
- let 端仰、const 聲明的變量只在 let 、const 命令所在的代碼塊 {} 內(nèi)有效田藐,在 {} 之外不能訪問荔烧。(塊級作用域)
- let 吱七、const都不能和它所在作用域內(nèi)的其他變量或函數(shù)擁有相同的名稱
- const 用于聲明一個或多個常量,聲明時必須進(jìn)行初始化鹤竭,且初始化后值不可再修改
- 在相同的作用域或塊級作用域中陪捷,不能使用 const 關(guān)鍵字來重置 var 和 let關(guān)鍵字聲明的變量
- 在相同的作用域或塊級作用域中,不能使用 const 關(guān)鍵字來重置 const 關(guān)鍵字聲明的變量
- 在相同的作用域或塊級作用域中诺擅,不能使用 var 關(guān)鍵字來重置 let 關(guān)鍵字聲明的變量
- 在相同的作用域或塊級作用域中,不能使用 let 關(guān)鍵字來重置 let 關(guān)鍵字聲明的變量
- 在相同的作用域或塊級作用域中啡直,不能使用 let 關(guān)鍵字來重置 var 關(guān)鍵字聲明的變量
- const 烁涌、let關(guān)鍵字在不同作用域,或不同塊級作用域中是可以重新聲明賦值的
var name = 'zyc'; // 全局變量
// 全局函數(shù)
function foo() {
console.log(name); //使用全局變量
}
console.log(foo) //運(yùn)行打印 函數(shù)體
foo(); // 運(yùn)行打泳泼佟: zyc
//全局函數(shù)
function bar() {
var name = 2; //函數(shù)局部變量(屬于當(dāng)前函數(shù)體)
foo(); // 這里調(diào)用全局函數(shù)撮执,運(yùn)行打印 zyc(調(diào)用的是棧內(nèi)存中保存的方法屬于全局作用域下不屬于bar 函數(shù)的嵌套函數(shù)所以無法讀取到bar函數(shù)定義的name)
}
console.log(bar) //運(yùn)行打印 函數(shù)體
bar();//全局函數(shù)調(diào)用
可以看成
{
var name = 'zyc'; // 全局變量
var foo;
foo = function () {
console.log(name); //使用全局變量
}
var bar;
bar = function(){
var name = 2; //函數(shù)局部變量(屬于當(dāng)前函數(shù)體)
foo(); // 這里調(diào)用全局函數(shù),運(yùn)行打印 zyc(調(diào)用的是棧內(nèi)存中保存的方法屬于全局作用域下不屬于bar函數(shù)的嵌套函數(shù)所以無法讀取到bar函數(shù)定義的name)
}
console.log(foo) //運(yùn)行打印 函數(shù)體
foo(); // 運(yùn)行打酉系ぁ: zyc
console.log(bar) //運(yùn)行打印 函數(shù)體
bar();//全局函數(shù)調(diào)用
}
在如
console.log(fn);
fn();
{
fn();
function fn() {
console.log(10)
};
fn();
}
fn();
看做
var fn;
console.log(fn);
fn();
{
fn = function(){
console.log(10)
};
fn();
fn();
}
fn();
- 函數(shù)聲明(函數(shù)名稱) 類似于 var抒钱,即會提升到全局作用域或函數(shù)作用域的頭部
- 函數(shù)聲明(函數(shù)整體) 還會提升到所在的花括號 {} 中的語句的頭部
可以把整個script當(dāng)做花括號{}
相關(guān)資料
JavaScript 變量
JavaScript let 和 const
JavaScript 聲明提升
JavaScript 作用域
Scope
函數(shù)作用域, 塊級作用域和詞法作用域
函數(shù)提升與函數(shù)的塊級作用域