欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript作用域與作用域鏈?zhǔn)褂弥攸c(diǎn)講解

 更新時(shí)間:2022年10月24日 09:04:54   作者:YinJie…  
當(dāng)代碼在一個(gè)環(huán)境中執(zhí)行時(shí),會(huì)創(chuàng)建變量對(duì)象的一個(gè)作用域鏈,作用域鏈的用途是保證對(duì)執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問,下面這篇文章主要給大家介紹了關(guān)于JavaScript作用域與作用域鏈的相關(guān)資料,需要的朋友可以參考下

作用域和作用域鏈方面的知識(shí)是JS的重點(diǎn),去面試十個(gè)有八個(gè)都會(huì)問你這塊的知識(shí),所以說這塊是特別特別的重要,下面我們好好理解一下作用域和作用域鏈到底是個(gè)什么:

先上一段代碼:

var a = 'jack';
function fn() {
    var a = 'frank';
}
console.log(a);

我們?cè)诤瘮?shù)里定義了一個(gè)a變量,在函數(shù)外也定義了一個(gè)a變量,那最后輸出的應(yīng)該是哪一個(gè)a的值呢?

這個(gè)時(shí)候就有了作用域這個(gè)概念了,簡(jiǎn)單地說作用域就是限制某個(gè)變量只能在某個(gè)區(qū)域內(nèi)有效。

作用域有全局作用域和局部作用域之分,變量同樣如此,在上例中,第一個(gè)a很顯然是一個(gè)全局變量,函數(shù)內(nèi)的a顯然是局部變量。全局變量擁有全局作用域而局部變量擁有局部作用域。這道題里console.log是在全局里調(diào)用a,那么毋庸置疑最后輸出的一定是'jack'。

這個(gè)時(shí)候我把函數(shù)代碼塊改為if代碼塊,看看最后應(yīng)該輸出什么呢

var a = 'jack';
if(true) {
    var a = 'frank';
}
console.log(a);

最后的結(jié)果a輸出的是'frank'。

實(shí)際上這里有一個(gè)大坑,千萬不要以為大括號(hào)封起來就一定是封閉環(huán)境,if里面的語(yǔ)句執(zhí)行完后就會(huì)自動(dòng)銷毀了,但是在javascript里if內(nèi)部定義的變量就會(huì)變?yōu)楫?dāng)前執(zhí)行環(huán)境的變量。當(dāng)前執(zhí)行環(huán)境在最外圍,所以if里面的a就變?yōu)槿肿兞苛?/p>

我們?cè)賮砜聪旅孢@段代碼分別應(yīng)該輸出什么呢?

for(var i = 0;i<3;i++) {
    break;
}
console.log(i);
k = 5;
while(k>1) {
    k--;
    var d = 10;
}
console.log(k);
console.log(d);

除了if代碼塊還有我們常見的for循環(huán),while循環(huán)也是相似的結(jié)果,我們不要被括號(hào)給迷惑了,在括號(hào)內(nèi)定義的變量不一定就是局部作用域,因此這里的i,k,d變量都是全局變量,這是輸出結(jié)果:

下面結(jié)合es6新增的塊級(jí)作用域做一個(gè)總的概括:

  • 在ES6中只要{ }沒有和函數(shù)結(jié)合在一起,那么應(yīng)該就是“塊級(jí)作用域”。
  • 在塊級(jí)作用域中,var定義的變量是全局變量,let定義的變量是局部變量。
  • 而在局部作用域也就是函數(shù)作用域中,無論是用var定義的變量還是用let定義的變量都是局部變量。
  • 無論是在塊級(jí)作用域還是局部作用域,省略變量前面的var或者let都會(huì)變成一個(gè)全局變量。

現(xiàn)在我們?cè)倩氐角懊娴睦?,這一次增加了全局變量b,在函數(shù)內(nèi)增加了兩個(gè)console.log輸出語(yǔ)句,最后再調(diào)用這個(gè)函數(shù),但是在函數(shù)里并沒有定義變量b,那最后會(huì)是什么結(jié)果呢

var a = 'jack';
var b = 'andy';
function fn() {
    var a = 'frank';
    console.log(a);
    console.log(b);
}
fn();
console.log(a);

輸出結(jié)果:

第二個(gè)console.log為什么會(huì)輸出全局變量andy呢?

這個(gè)時(shí)候就有了作用域鏈的概念了,簡(jiǎn)單的說作用域表示區(qū)域,作用域鏈表示次序

現(xiàn)在我們把眼光放在函數(shù)fn里,第一行定義了a是局部變量,第二行輸出這個(gè)a,但是整個(gè)代碼里定義了兩個(gè)a,那么就需要?jiǎng)倓傉f到的作用域鏈來決定到底先用哪個(gè)變量。

javascript會(huì)先看函數(shù)內(nèi)有沒有這個(gè)變量a,如果沒有再去函數(shù)的外圍看有沒有這個(gè)變量,這里作用域鏈就幫我們安排好了這個(gè)次序。

所以,函數(shù)內(nèi)定義了變量a為'frank',那么第二行就會(huì)輸出'frank',第三行要輸出變量b,我們先看函數(shù)內(nèi)有沒有這個(gè)變量,發(fā)現(xiàn)沒有,再去外圍發(fā)現(xiàn)有全局變量b,那么輸出的就是這個(gè)值,我們?cè)賮砜醋詈笠粋€(gè)console.log(a),因?yàn)樗谌址秶鷥?nèi),所以只能訪問全局變量a。

也就是說:作用域鏈只能向上查找,最終找到全局。不能同級(jí)(局部)或者向下查找

我們?cè)倏催@一段代碼:

var a = 'jack';
function fn() {
    console.log(a);
    var a = 'andy';
    console.log(a);
}
fn();

我們思考一下會(huì)輸出什么呢?

輸出結(jié)果:

稍微有點(diǎn)js經(jīng)驗(yàn)的同學(xué)應(yīng)該都會(huì)答對(duì),因?yàn)橛凶兞刻嵘?,變量a在第一行就被聲明了,只不過沒有被賦值。下面修改一下代碼,大家再看看會(huì)輸出什么:

var a = 'jack';
function fn() {
    console.log(a);
    var a = 'andy';
    console.log(ss());
    function ss() {
        return a;
    }
}
fn();

我們?cè)趂n函數(shù)內(nèi)又添加了一個(gè)函數(shù)ss,并且在這個(gè)函數(shù)的頂部就調(diào)用了這個(gè)函數(shù)。不僅函數(shù)內(nèi)聲明的變量會(huì)被提升,函數(shù)內(nèi)的函數(shù)也會(huì)被提升,而且函數(shù)的提升會(huì)比變量更優(yōu)先

那么,在javascript中這段代碼實(shí)際上是這樣被執(zhí)行的:

var a = 'jack';
function fn() {
    function ss() {
        return a;
    }
    var a;
    console.log(a);
    a = 'andy';
    console.log(ss());
}
fn();

先把函數(shù)聲明提升到首行,再聲明變量a,然后輸出a,a沒有被賦值,所以是undefined,然后a被賦值為'andy',最后調(diào)用函數(shù)ss,返回的就是andy。

到此這篇關(guān)于JavaScript作用域與作用域鏈?zhǔn)褂弥攸c(diǎn)講解的文章就介紹到這了,更多相關(guān)JS作用域與作用域鏈內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論