JavaScript高程學習筆記之函數表達式(7)

目錄javascript



  • 函數表達式的特徵
  • 使用函數實現遞歸
  • 使用閉包定義私有變量java

    1. 遞歸

    argument.callee:一個指向正在執行函數的指針,嚴格模式下會出錯
    命名函數表達式,嚴格和非嚴格都不會出錯
var factorial = (function f(num){
    if (num <= 1){
        return 1;
    }else {
        return num * f(num - 1);
    }
});

2. 閉包

閉包是指有權訪問另外一個函數做用域中變量的函數
建立閉包的常見方式:在一個函數內部建立另外一個函數
過分使用閉包會致使內存佔用過多,要慎重使用閉包

2.1 閉包與變量

閉包只能取得包含函數中任何變量的最後一個值app

function createFunctions(){
                var result = new Array();
                
                for (var i=0; i < 10; i++){
                    result[i] = function(){
                        return i;
                    };
                }
                
                return result;
            }

表面看每一個函數都返回本身的索引值,實際上每一個函數都返回10
由於每一個函數的做用域鏈中都保存着createFunctions()函數的活動對象,它們引用同一變量
能夠建立另外一個匿名函數讓閉包行爲符合預期函數

function createFunctions(){
                var result = new Array();
                
                for (var i=0; i < 10; i++){
                    result[i] = function(num){
                        return function(){
                            return num;
                        };
                    }(i);
                }
                
                return result;
            }
2.2 關於this對象

匿名函數的執行環境具備全局性,this對象一般指向windowthis

var name = "The Window";
        
        var object = {
            name : "My Object",
        
            getNameFunc : function(){
                return function(){
                    return this.name;
                };
            }
        };
        
        alert(object.getNameFunc()());  //"The Window"

把外部做用域中的this對象保存到閉包可以訪問到的變量中prototype

var name = "The Window";
            
            var object = {
                name : "My Object",
            
                getNameFunc : function(){
                    var that = this;
                    return function(){
                        return that.name;
                    };
                }
            };
            
            alert(object.getNameFunc()());  //"MyObject"
2.3 內存泄漏

若是閉包的做用域鏈保存着一個HTML元素意味着該元素將沒法被銷燬指針

function assignHandler(){
    var element = document.getElementById("someElement");
    element.onclick = function(){
        alert(element.id);
    };
}

匿名函數對assignHandler()活動對象的引用,element引用次數最少是1,佔用內存沒法被回收
修改代碼解決內存泄漏問題code

function assignHandler(){
    var element = document.getElementById("someElement");
    var id = element.id;
    element.onclick = function(){
        alert(id);
    };

    element = null;
}

3. 模仿塊級做用域

(function(){
    //這裏是塊級做用域
})();

匿名函數中定義的變量執行後銷燬
不會搞亂全局做用域component

4. 私有變量

私有變量包括函數的參數,局部變量和函數內部定義的其餘函數
特權方法:有權訪問私有變量和私有函數的公有方法成爲特權方法

4.1 靜態私有變量

靜態的,由全部實例共享的屬性

(function(){
            
                var name = "";
                
                Person = function(value){                
                    name = value;                
                };
                
                Person.prototype.getName = function(){
                    return name;
                };
                
                Person.prototype.setName = function (value){
                    name = value;
                };
            })();
            
            var person1 = new Person("Nicholas");
            alert(person1.getName());   //"Nicholas"
            person1.setName("Greg");
            alert(person1.getName());   //"Greg"
                               
            var person2 = new Person("Michael");
            alert(person1.getName());   //"Michael"
            alert(person2.getName());   //"Michael"
4.2 模塊模式

模塊模式:爲單例建立私有變量和特權方法
單例:只有一個實例的對象
JavaScript中用對象字面量的方式建立單例對象
若是建立一個對象並以某些數據對其初始化,同時還要公開一些訪問私有數據的方法,就能夠用模塊模式

function BaseComponent(){
            }
            
            function OtherComponent(){
            }
        
            var application = function(){
            
                //private variables and functions
                var components = new Array();
            
                //initialization
                components.push(new BaseComponent());
            
                //public interface
                return {
                    getComponentCount : function(){
                        return components.length;
                    },
            
                    registerComponent : function(component){
                        if (typeof component == "object"){
                            components.push(component);
                        }
                    }
                };
            }();

            application.registerComponent(new OtherComponent());
            alert(application.getComponentCount());  //2
4.3 加強的模塊模式

返回對象以前加入對其加強的代碼
適合單例必須是某種類型的實例,同時還必須添加某些屬性和方法對其加以加強的狀況

function BaseComponent(){
            }
            
            function OtherComponent(){
            }
        
            var application = function(){
            
                //private variables and functions
                var components = new Array();
            
                //initialization
                components.push(new BaseComponent());
            
                //create a local copy of application
                var app = new BaseComponent();
            
                //public interface
                app.getComponentCount = function(){
                    return components.length;
                };
            
                app.registerComponent = function(component){
                    if (typeof component == "object"){
                        components.push(component);
                    }
                };
            
                //return it
                return app;
            }();

            alert(application instanceof BaseComponent);
            application.registerComponent(new OtherComponent());
            alert(application.getComponentCount());  //2
相關文章
相關標籤/搜索