作用域
- JavaScript中作用域的概念和C語(yǔ)言一樣, 也分為全局作用域和局部作用域
- 全局作用域
- 在任何地方都可以訪問(wèn)到的就是全局作用域
- 在script標(biāo)簽中或一個(gè)獨(dú)立js文件中定義的就是全局作用域
<script>
var num = 10; // 該變量是全局作用域
function test() {
// 在函數(shù)中訪問(wèn)全局作用域num變量
console.log("test中"+num);
}
test();
// 在外面訪問(wèn)全局作用域num變量
console.log("外部"+num);
</script>
function test() { // 該函數(shù)是全局作用域
console.log("test函數(shù)");
}
// 在外面訪問(wèn)全局作用域test函數(shù)
test();
function demo() {
// 在函數(shù)中訪問(wèn)全局作用域test函數(shù)
test();
}
demo();
- 局部作用域
- 只在固定的代碼片段內(nèi)可訪問(wèn)到的變量,例如函數(shù)內(nèi)部。對(duì)應(yīng)局部作用域(函數(shù)作用域)
- 寫(xiě)在函數(shù)內(nèi)部的都是局部作用域, 只能在當(dāng)前函數(shù)內(nèi)訪問(wèn)
<script>
function test() {
var num = 123; // 該變量是局部作用域
// 可以在同一個(gè)局部作用域中訪問(wèn)
console.log("test中"+ num);
}
// 不能在局部范圍以外訪問(wèn)
console.log("外部"+num);
</script>
<script>
function test() {
function demo() { // 該函數(shù)是局部作用域
console.log("demo函數(shù)");
}
// 可以在同一個(gè)局部作用域中訪問(wèn)
demo();
}
// 不能在局部范圍以外訪問(wèn)
demo();
</script>
- 注意點(diǎn):
- 如果在函數(shù)中定義變量時(shí),如果不添加var關(guān)鍵字, 這個(gè)變量是一個(gè)全局變量
<script>
function test() {
// 企業(yè)開(kāi)發(fā)千萬(wàn)不要這么寫(xiě)
num = 123;
console.log(num);
}
test();
console.log(num);
</script>
- 任何一對(duì)花括號(hào)({和})中的語(yǔ)句集都屬于一個(gè)塊,在這之中定義的所有變量在代碼塊外都是不可見(jiàn)的,我們稱之為塊級(jí)作用域。
- 在es5之前沒(méi)有塊級(jí)作用域的的概念,只有函數(shù)作用域,現(xiàn)階段可以認(rèn)為JavaScript沒(méi)有塊級(jí)作用域
作用域鏈
- JavaScript代碼中至少有一個(gè)作用域, 即全局作用域。
- 凡是代碼中有函數(shù),那么這個(gè)函數(shù)就構(gòu)成另一個(gè)作用域。
- 如果函數(shù)中還有函數(shù),那么在這個(gè)作用域中就又可以誕生一個(gè)作用域。
- 將這樣的所有的作用域列出來(lái),可以形成的結(jié)構(gòu)就稱之為作用域鏈。
<script>
var num = 123; // 0級(jí)作用域鏈
function test() { // 0級(jí)作用域鏈
var num = 666; // 1級(jí)作用域鏈
console.log(num);
function demo() { // 2級(jí)作用域鏈
var num = 777;
console.log(num);
}
demo();
}
test();
console.log(num);
</script>

再直白一點(diǎn): 訪問(wèn)時(shí)就是C語(yǔ)言中的就近原則
預(yù)解析
- JavaScript代碼的執(zhí)行是由瀏覽器中的JavaScript解析器來(lái)執(zhí)行的。
- JavaScript解析器執(zhí)行JavaScript代碼的時(shí)候,分為兩個(gè)過(guò)程:
- 預(yù)解析過(guò)程
- 代碼執(zhí)行過(guò)程
- 預(yù)解析過(guò)程:
- 把變量的聲明提升到當(dāng)前作用域的最前面,只會(huì)提升聲明,不會(huì)提升賦值。
- 把函數(shù)的聲明提升到當(dāng)前作用域的最前面,只會(huì)提升聲明,不會(huì)提升調(diào)用。
- 先提升var,在提升function。
- 案例1
<script>
console.log(num); // undefined
var num = 123;
</script>
<script>
// 把變量的聲明提升到當(dāng)前作用域的最前面
var num;
console.log(num);
num = 123;
</script>
- 案例2:
<script>
test();
function test() {
console.log("hello world");
}
</script>
<script>
test();
alert(test);
function test() {
console.log("hello world");
}
</script>
<script>
// 把函數(shù)的聲明提升到當(dāng)前作用域的最前面
function test() {
console.log("hello world");
}
test();
alert(test);
</script>
- 預(yù)解析練習(xí)
var num = 123;
fun();
function fun() {
console.log(num);
var num = 666;
}
/*
var num;
function fun() {
var num;
console.log(num);
num = 666;
}
num = 123;
fun();
*/
var a = 666;
test();
function test() {
var b = 777;
console.log(a);
console.log(b);
var a = 888;
}
/*
var a;
function test() {
var b;
var a;
b = 777;
console.log(a);
console.log(b);
a = 888;
}
a = 666;
test();
*/
- 注意點(diǎn):
- 變量和函數(shù)同名時(shí), 函數(shù)的優(yōu)先級(jí)高
<script>
console.log(num);
function num() {
console.log("hello world");
}
var num = 666;
console.log(num);
/*
function num() {
console.log("hello world");
}
var num;
console.log(num);
num = 666;
console.log(num);
*/
</script>
不同方式定義函數(shù)區(qū)別
- 預(yù)解析時(shí)提升的方式不同
<script>
// 1.函數(shù)聲明
test();
function test() {
console.log("指趣學(xué)院");
}
// 2.函數(shù)表達(dá)式
demo(); // 報(bào)錯(cuò)
var demo = function () {
console.log("www.it666.com");
}
/*
function test() {
console.log("指趣學(xué)院");
}
var demo;
test();
demo();
demo = function () {
console.log("www.it666.com");
}
*/
</script>
- 新舊版本瀏覽器預(yù)解析處理方式不同
<script>
/*
在新版本瀏覽器中, 代碼塊中的函數(shù)不會(huì)被提升
在舊版本瀏覽器中, 代碼塊中的函數(shù)會(huì)被提升
新版本輸出"指趣學(xué)院"
老版本輸出"www.it666.com"
*/
if(true){
function test() {
console.log("指趣學(xué)院");
}
}else{
function test() {
console.log("www.it666.com");
}
}
test();
</script>
<script>
var test;
if(true){
test = function () {
console.log("指趣學(xué)院");
}
}else{
test = function() {
console.log("www.it666.com");
}
}
test();
</script>