JS作用域和閉包核心面試題分析


作用域和閉包-執行上下文:

變量提升(寫代碼時千萬不要先使用再定義)

    <script>
        console.log(a);//undefined
        var a=10;

        fn('cyy',18);
        function fn(name,age){
            age=20;
            console.log(name,age);//cyy 20
            var age;
        }
    </script>

 

函數聲明存在提升,函數表達式不存在提升

    <script>
        fn1();//函數聲明  不會報錯
        function fn1(){}

        fn2();//函數表達式  報錯
        var fn2=function(){}
    </script>

 

    <script>
        fn('cyy');
        function fn(name){
            console.log(this);
            console.log(arguments);
            console.log(name);
        }
    </script>

 

 

作用域和閉包-this:

this要在執行時才能確認值,定義時無法確認

    <script>
        var a={
            name:'cyy',
            fn(){
                console.log(this.name);
            }
        }
        a.fn();//this===a
        a.fn.call({name:'cyy2'});//this==={name:'cyy2'}
        var fn1=a.fn;
        fn1();//this===window
    </script>

 

this:

作為構造函數執行

作為對象屬性執行

作為普通函數執行

call  apply  bind

    <script>
        //構造函數
        function Foo(name){
            this.name=name;
        }
        var f=new Foo('cyy');

        //作為一個對象的屬性
        var obj={
            name:'cyy',
            fn(){
                console.log(this.name);
            }
        }
        obj.fn();

        //普通函數的this
        function fn(){
            console.log(this);
        }
        fn();//this===window

        //call  apply  bind
        function fn1(name,age){
            console.log(name);
            console.log(this);
        }
        fn1.call({x:10},'cyy2',18);
        fn1.apply({x:20},['cyy3',19]);

        var fn2=function(name,age){
            console.log(name);
            console.log(this);
        }.bind({x:30});
        fn2('cyy4',20);
    </script>

 

 

作用域和閉包-作用域:

沒有塊級作用域,只有函數和全局作用域

    <script>
        //無塊級作用域
        if(true){
            var name='cyy';
        }
        console.log(name);

        //有全局和函數作用域
        var a=10;
        function fn(){
            var a=20;
            console.log('fn:'+a);
        }
        fn();
        console.log('global:'+a);
    </script>

 

 

    <script>
        //作用域鏈
        var a=10;
        function fn(){
            var b=20;
            //當前函數作用域內沒有定義的變量,即自由變量
            console.log(a);
            console.log(b);
        }
        fn();
    </script>

 

 

作用域和閉包--閉包:

閉包的使用場景:

1、函數作為返回值

2、函數作為參數傳遞

    <script>
        //函數作為返回值
        function F1(){
            var a=100;
            return function(){
                console.log(a);//a是自由變量,向父級作用域去尋找---函數定義時的作用域
            }
        }
        var f1=F1();
        var a=200;
        f1();//100

        //函數作為參數傳遞
        function F2(){
            var b=100;
            return function(){
                console.log(b);//b是自由變量,向父級作用域去尋找---函數定義時的作用域
            }
        }
        var f2=F2();
        function F3(fn){
            var b=300;
            fn();
        }
        F3(f2);//100
    </script>

 

作用域和閉包--解題:

    <script>
        //錯誤的寫法
        //點擊結果都是10
        var i;
        for(i=0;i<10;i++){
            var a=document.createElement('a');
            a.innerHTML=i;
            a.addEventListener('click',function(e){
                e.preventDefault();
                alert(i);//i是自由變量,要去父作用域尋找值;for循環不是作用域,所以獲取到的i是循環結束的全局變量i=10
            })
            document.body.appendChild(a);
        }


        //正確寫法,自執行的匿名函數形成函數作用域
        var i;
        for(i=0;i<10;i++){
            (function(i){
                //形成函數作用域,i不再是全局變量
                var a=document.createElement('a');
                a.innerHTML=i;
                a.addEventListener('click',function(e){
                    e.preventDefault();
                    alert(i);//i是自由變量,要去父作用域尋找值
                })
                document.body.appendChild(a);                
            })(i);
        }
    </script>

 

    <script>
        //閉包的應用
        function isFirstLoad(){
            var _list=[];//通常_開頭的變量表示私有
            return function(id){
                if(_list.indexOf(id) >= 0){//不是第一次出現
                    return false;
                }else{
                    _list.push(id);
                    return true;
                }
            }
        }
        var firstload=isFirstLoad();
        console.log(firstload(10));//true
        console.log(firstload(10));//false
        console.log(firstload(20));//true
    </script>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM