JavaScript高程学习笔记之函数表达式(7)


[TOC]javascript


  • 函数表达式的特征
  • 使用函数实现递归
  • 使用闭包定义私有变量

1. 递归

argument.callee:一个指向正在执行函数的指针,严格模式下会出错 命名函数表达式,严格和非严格都不会出错java

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
相关文章
相关标签/搜索