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



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

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

var factorial = (function f(num){
    if (num <= 1){
        return 1;
    }else {
        return num * f(num - 1);
    }
});
2. 闭包

闭包是指有权访问另一个函数作用域中变量的函数
创建闭包的常见方式:在一个函数内部创建另一个函数
过度使用闭包会导致内存占用过多,要慎重使用

2.1 闭包与变量

闭包只能取得包含函数中任何变量的最后一个值

            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对象通常指向window

        var name = "The Window";

        var object = {
            name : "My Object",

            getNameFunc : function(){
                return function(){
                    return this.name;
                };
            }
        };

        alert(object.getNameFunc()());  //"The Window"

把外部作用域中的this对象保存到闭包能够访问到的变量中

            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,占用内存无法被回收
修改代码解决内存泄漏问题

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

    element = null;
}
3. 模仿块级作用域
(function(){
    //这里是块级作用域
})();

匿名函数中定义的变量执行后销毁
不会搞乱全局作用域

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值