js作用域、閉包

一、作用域

作用域:變量生效(可以被訪問)的范圍,用來控制變量的可見性和生命周期。

全局作用域:不單獨(dú)屬于某一個函數(shù)的變量就是一個全局變量,在任何位置(普通函數(shù)、構(gòu)造函數(shù)、字面量對象中)都可以訪問到這個變量。

局部作用域:在函數(shù)中使用var定義的變量是局部變量。
注意:在js中塊級(也就是大括號)的概念并不像其他語言那樣完善(ECMA6中完善了),在其他語言中,一對大括號中的變量就是一個局部變量,但是在js中只有在一個函數(shù)中定義的變量才是一個局部變量。

作用域鏈:在多級作用域嵌套時,如果當(dāng)前作用域內(nèi)找不到所需要的變量,則向父級作用域?qū)ふ?,一直找到全局作用域,但不會向下尋找?/p>

變量提升:

var a = 12;
function fun1() {
alert("1"+a); // 未定義,內(nèi)部定義了a,變量提升,并未賦值,所以a是未定義
var a = 23;//由于這行代碼導(dǎo)致變量提升了
alert("2"+a);
a = 14;
}
fun1();
alert("3"+a);

面試題:

var a = 1;
            for (var i = 0; i < 5; i++) {
                var a = i;
            }
            // a = 4
            function fn1() {

                alert(a);   //  undefine
                var a = 2;
                alert(a);   // 2
                
            }
            alert(fn1());  //undefine
            alert(a);     //  4
            alert(abc(2)); // 報錯

二、匿名函數(shù)

匿名函數(shù):沒有函數(shù)名字,只有函數(shù)體的函數(shù)叫匿名函數(shù)。
區(qū)分:具名函數(shù),有函數(shù)名的函數(shù)。

var fn=function (){
                alert('hello');
            }

匿名函數(shù)使用場景:
1、通過DOM0級給標(biāo)簽添加事件函數(shù),這些函數(shù)全是匿名函數(shù)。
事件函數(shù):通過用戶事件觸發(fā)執(zhí)行的函數(shù),比如某個按鈕的click事件。

2、把匿名函數(shù)當(dāng)做另一個函數(shù)的參數(shù)傳遞,比如:定時器。

3、使用匿名函數(shù)模擬塊級作用域。

(function(){
                for(var i=0;i<4;i++){
                    
                }
            })();

4、匿名函數(shù)充當(dāng)閉包

三、閉包

閉包:在函數(shù)執(zhí)行完畢后,向外返回另一個函數(shù)。在返回的函數(shù)中,使用到一個局部變量,因?yàn)槌薪舆@個返回函數(shù)的變量是全局的,為了保證全局變量正常訪問,所以全局變量中所引用的局部變量生命周期也被無限的延長。
閉包能夠讀取其他函數(shù)內(nèi)部變量。

function fn1(){
                var i=12;
                function fn2(){
                    console.log(i);
                    return i+3
                }
                return fn2;
            }
            
            var result=fn1(); //得到fn2函數(shù)
            console.log(result());//得到15
//fn1是fn2的?函數(shù),?fn2被賦給了?個全局變量,這導(dǎo)致fn2始終在內(nèi)存中,
//?fn2的存在依賴于fn1,因此fn1也始終在內(nèi)存中,不會在調(diào)?結(jié)束后,被垃
//圾回收機(jī)制(garbage collection)回收。

閉包的用途:
1、可以在全局作用域讀取函數(shù)內(nèi)部的變量。

2、讓這些局部變量的值始終保持在內(nèi)存中。

3、利用閉包解決使用循環(huán)添加事件的BUG。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script type="text/javascript">
            window.onload=function(){
                var btnArr=document.querySelectorAll('.btn');
                for(var i=0;i<btnArr.length;i++){                   
                    (function(num){
//num變量是函數(shù)的形參,函數(shù)在每次執(zhí)行時都會重新開辟內(nèi)存空間來存放這個形參                     
//所以給標(biāo)簽添加的點(diǎn)擊事件中使用到的num變量都是獨(dú)一無二的,num變量中的
//值是當(dāng)前遍歷標(biāo)簽時的下標(biāo)值
                        btnArr[num].onclick=function(){
//匿名函數(shù)在執(zhí)行時,給事件綁定了這個函數(shù),函數(shù)中操作了一個局部變量。該
//函數(shù)執(zhí)行時一定是在全局變量作用域中執(zhí)行的,所以為了保證在全局作用域中
//正常觸發(fā)該函數(shù),num變量也就變成了全局變量。
                            alert(num+1);
                        }
                    })(i);
                }
            }
        </script>
    </head>
    <body>
        <button class="btn">1</button>
        <button class="btn">2</button>
        <button class="btn">3</button>
        <button class="btn">4</button>
    </body>
</html>

4、閉包解決下拉選擇框的BUG

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            *{
                margin: 0;
                padding: 0;             
            }
            ul{
                width: 500px;
                margin: auto;
                margin-top: 20px;
            }
            li{
                float: left;
                list-style: none;
                width: 100px;
                height: 21px;
                background: pink;
                text-align: center;
                cursor: pointer;
            }
            div{
                display: none;
                background: greenyellow;
            }
            .active{
                background: indianred;
            }
        </style>
        <script type="text/javascript">
            window.onload=function(){
                var lis=document.querySelectorAll('li');
                var divs=document.querySelectorAll('div');
                for(var i=0;i<lis.length;i++){
                    (function(indexs){
                        lis[indexs].onmouseover=function(){
                            lis[indexs].className='active';
                            divs[indexs].style.display='block';
                        }
                    })(i);
                    (function(indexs){
                        lis[indexs].onmouseout=function(){
                            divs[indexs].style.display='none';
                            lis[indexs].className='';
                        }
                    })(i);
                }
            }
        </script>
    </head>
    <body>
        <ul>
            <li>
                <span>
                    菜單一
                </span>
                <div>
                    <p>菜單一內(nèi)容</p>
                    <p>菜單一內(nèi)容</p>
                    <p>菜單一內(nèi)容</p>
                    <p>菜單一內(nèi)容</p>
                </div>
            </li>
            <li>
                <span>
                    菜單二
                </span>
                <div>
                    <p>菜單二內(nèi)容</p>
                    <p>菜單二內(nèi)容</p>
                    <p>菜單二內(nèi)容</p>
                    <p>菜單二內(nèi)容</p>
                </div>
            </li>
            <li>
                <span>
                    菜單三
                </span>
                <div>
                    <p>菜單三內(nèi)容</p>
                    <p>菜單三內(nèi)容</p>
                    <p>菜單三內(nèi)容</p>
                    <p>菜單三內(nèi)容</p>
                </div>
            </li>
            <li>
                <span>
                    菜單四
                </span>
                <div>
                    <p>菜單四內(nèi)容</p>
                    <p>菜單四內(nèi)容</p>
                    <p>菜單四內(nèi)容</p>
                    <p>菜單四內(nèi)容</p>
                </div>
            </li>
            <li>
                <span>
                    菜單五
                </span>
                <div>
                    <p>菜單五內(nèi)容</p>
                    <p>菜單五內(nèi)容</p>
                    <p>菜單五內(nèi)容</p>
                    <p>菜單五內(nèi)容</p>
                </div>
            </li>
        </ul>
    </body>
</html>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容