Javascript漂流記(上)__作用域鏈、閉包、立即執行函數

一、作用域[[scope]]:
    存儲了執行期上下文的集合(作用域鏈)
    參照下圖代碼:
    a函數被定義時:a.[[scope]]--> 0:GO{}

    a函數執行時:a.[[scope]]--> 0:aAO{}
                                                 1:GO{}

    a函數執行時,b函數被定義:b.[[scope]]-->0:aAO{}
                                                                        1:GO{}

    b函數毫不客氣地帶上了老爹a函數的勞動成果。


    b函數執行時:b.[[scope]]-->0:bAO{}
                                                1:aAO{}
                                                2:GO{}

    在哪個函數裏查找變量,就從哪個函數的作用域鏈的頂端依次向下查找
    b函數執行結束,摧毀自己的執行期上下文,迴歸到被定義時的狀態,等待下一次執行
    a函數執行結束,摧毀自己的執行期上下文(同時摧毀了整個b函數),迴歸到被定義時的狀態,等待下一次執行

 

二、閉包:還是舉慄說明

                  當a函數將其內部的b函數return,並賦給外部變量demo時,
                  此時的b函數保存了a函數執行時的作用域鏈,不會被釋放。形成閉包。


 

       如此一來,若過多的作用域鏈不被釋放,佔用大量內存,造成內存泄露。

       閉包的應用:

               1、用做緩存(存儲結構)          

            function eater(){
                var food = '';
                var obj = {
                    eat: function() {
                        console.log('I am eating ' + food);
                        food = '';
                    },
                    push: function(myFood){
                        food = myFood;
                    }
                }
                return obj;
            }
            var eater1 = eater();
            eater1.push('banana');
            eater1.eat();

               2、實現公有變量,函數累加器

            function add(){
                var count = 0;
                function demo(){
                    count++;
                    console.log(count);
                }
                return demo;
            }
            var counter = add();
            counter();//1
            counter();//2
            counter();//3

               3 、實現屬性私有化(第二塊代碼爲聖盃模式,後續繼承會涉及),別人訪問不到,自己可以操作。

            function Person(name,club){
                var prepareClub = 'Laker';

                this.name = name;
                this.club = club;
                this.changeClub = function(){
                    this.club = prepareClub;
                }
                this.changePrepareClub = function(target){
                    prepareClub = target;
                }
                this.sayPrepareClub = function(){
                    console.log(prepareClub);
                }
            }   
            var person = new Person('Jame','Heat');

                    下圖代碼爲聖盃模式,後續繼承模式會詳細說明。

            var inherit = (function(){
                var F = function(){};
                return function(Target,Origin){
                    F.prototype = Orgin.prototype;
                    Target.prototype = new F();
                    Target.prototype.constructor = Target;
                    Target.prototype.uber = Origin.prototype;
                }
            }());

               4、模塊化開發,防止污染全局變量

            var name = 'bcd';
            var initJack = (function(){
                var name = 'abc';
                function callName(){
                    console.log(name);
                }
                return function(){
                    callName();
                }
            }());
            initJack();

 

三、立即執行函數:有些函數只需要執行一次,初始化功能,執行完立即釋放。

            var num = (function(a,b){
                return a + b;
	        }(3,5));
            console.log(num);//8

        立即執行函數拓展:
               只有表達式才能被執行符號執行!!!如下列代碼,+、-將函數test轉換爲表達式
               能被執行符號執行的函數表達式,自動放棄函數名稱。

            +function test(){
                console.log('a');
            }();
            
            -function test(){
                console.log('b');
            }();

               經典鄙視題 :以下代碼如何執行?

            function demo(a,b,c,d){
                return a + b + c + d;
            }(1,2,3,4)

四、閉包的防範:如下兩段代碼,感受一下。

            function test(){
                var arr = [];
                for(var i = 0; i < 10; i++){
                    arr[i] = function(){
                        console.log(i);//打印10個10
                    }
                }
                return arr;
            }
            var myArr = test();
            for(var j = 0; j < 10; j++){
                myArr[j]();
            }
            function test(){
                var arr = [];
                for(var i = 0; i < 10; i++){
                    (function(j){
                        arr[j] = function(){
                            console.log(j);//0123456789
                        }
                    }(i));
                }
                return arr;
            }
            var myArr = test();
            for(var j = 0; j < 10; j++){
                myArr[j]();
            }

以上內容屬二哥原創,整理自 "渡一教育Javascript課程" ,一個值得推薦的"渡一教育"。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章