JavaScript的函数闭包使用

一、模仿块级作用域

    JavaScript 没有块级作用域的概念,那么可以模拟像java中将很多变量私有化封装起来,保护数据,防止数据泄漏,封装细节,这样安全性和可控性更高

  function box(count) {
        for (var i=0; i<count; i++) {     //块级作用域(JS中没有这个东西)
        }
        alert(i); //i 不会因为离开了 for 块就失效
    }
    box(2);    //结果是2,还是可以访问的
  function box(count) {
        for (var i=0; i<count; i++) {     //块级作用域(JS中没有这个东西)
        }
        var i;             //就算重新声明,也不会前面的值
        alert(i); //i 不会因为离开了 for 块就失效
    }
    box(2);    //结果是2,还是可以访问的

    以上两个例子,说明 JavaScript 没有块级语句的作用域,if () {} for () {}等没有作用域,如果有,出了这个范围 i 就应该被销毁了。就算重新声明同一个变量也不会改变它的值。

    JavaScript 不会提醒你是否多次声明了同一个变量;遇到这种情况,它只会对后续的声明视而不见(如果初始化了,当然还会执行的)。使用模仿块级作用域可避免这个问题。

二、模仿块级作用域(私有作用域)

/*
    (function () {
        //这里是块级作用域
    })();
*/
    function box(count) {
        (function () {
            for (var i = 0; i<count; i++) {
                alert(i);//只能在这里i才是有效的才是能访问的
            }
        })();
        alert(i); //这里i已经出了作用域   报错,无法访问
    }
    box(2);

    使用了块级作用域(私有作用域)后,匿名函数中定义的任何变量,都会在执行结束时被销毁。这种技术经常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数。
    一般来说,我们都应该尽可能少向全局作用域中添加变量和函数。在大型项目中,多人开发的时候,过多的全局变量和函数很容易导致命名冲突,引起灾难性的后果。
    如果采用块级作用域(私有作用域),每个开发者既可以使用自己的变量,又不必担心搞乱全局作用域。

    (function () {
        var box = [1,2,3,4];
        alert(box);
    })();
    alert(box);//box 出来就不认识了

    在全局作用域中使用块级作用域可以减少闭包占用的内存问题,因为没有指向匿名函数的引用。只要函数执行完毕,就可以立即销毁其作用域链了。

三、私有变量

    JavaScript 没有私有属性的概念;所有的对象属性都是公有的。不过,却有一个私有变量的概念。任何在函数中定义的变量,都可以认为是私有变量,因为不能在函数的外部访问这些变量。

function box() {
  var age = 100; //私有变量,外部无法访问,只能返回
}

    而通过函数内部创建一个闭包,那么闭包通过自己的作用域链也可以访问这些变量。而利用这一点,可以创建用于访问私有变量的公有方法。

  function Box(){
        this.age = 100;                    //可以访问,公有的
        this.run = function(){        //可以访问,公有的
            return "运行中....";
        }
    }
    var box = new Box();
    alert(box.age);
    alert(box.run());
    function Box() {
        var age = 100;                         //私有变量

        function run() {                     //私有函数
            return ‘运行中...‘;
        }

        this.get = function () {             //对外公共的特权方法
            return age + run();
        };
    }
    var box = new Box();
    alert(box.get());

    可以通过构造方法传参来访问私有变量。

    function Person(value) {
        var user = value; //这句其实可以省略
        this.getUser = function () {
            return user;
        };
        this.setUser = function (value) {
            user = value;
        };
    }
    var box = new Person("hua");
    alert(box.getUser());
    box.setUser(4);
    alert(box.getUser());

    但是对象的方法,在多次调用的时候,会多次创建。

  function Person(value) {
        var user = value; //这句其实可以省略
        this.getUser = function () {
            return user;
        };
        this.setUser = function (value) {
            user = value;
        };
    }
    var box = new Person("hua");
    alert(box.getUser());
    var box2 = new Person("kkk");
    alert(box.getUser());//结果还是hua,说明setUser方法没有共享

    可以使用静态私有变量来避免这个问题。

 

四、静态私有变量

    通过块级作用域(私有作用域)中定义私有变量或函数,同样可以创建对外公共的特权方法。

  (function () {
        var age = 100;                //私有变量
        function run() {
            return ‘运行中...‘;
        }
        //function Box(){}                //构造方法,在函数里写构造函数不支持,因为私有作用域里的函数,外部无法访问,所以要做成全局的,如下
        Box = function (value){            //全局构造方法
            age = value;
        };
        Box.prototype.getAge = function () {         //原型方法,只生成一个地址
            return age + run();
        };
        Box.prototype.setAge = function(value){
            age = value;
        }
    })();

    var box1 = new Box(23);
    alert(box1.getAge());
    var box2 = new Box(43);
    alert(box2.getAge());
    box2.setAge(76);
    alert(box1.getAge());//使用box2设置了age的值,再使用box1获取age的时候变成了box2设置的值,说明共享了

    使用了 prototype 导致方法共享了,而 age也就变成静态属性了。(所谓静态属性,即共享于不同对象中的属性)。

五、模块模式

    之前采用的都是构造函数的方式来创建私有变量和特权方法。那么对象字面量方式就采用模块模式来创建。

var box = function () {
        var age = 100;
        function run() {
            return ‘运行中...‘;
        }
        return { //直接返回对象
            go : function () {
                return age + run();
            }
        };
    }();

    //上面的直接返回对象的例子,也可以这么写:
    var box = function () {
        var age = 100;
        function run() {
            return ‘运行中...‘;
        }
        var obj = { //创建字面量对象
            go : function () {
                return age + run();
            }
        };
        return obj; //返回这个对象
    }();

    字面量的对象声明,其实在设计模式中可以看作是一种单例模式,所谓单例模式,就是永远保持对象的一个实例。

  function Desk() {};
        var box = function () {
        var age = 100;
        function run() {
            return ‘运行中...‘;
        }
        var desk = new Desk(); //可以实例化特定的对象
        desk.go = function () {
            return age + run();
        };
        return desk;
    }();
    alert(box.go());

    增强的模块模式,这种模式适合返回自定义对象,也就是构造函数。

时间: 2024-10-12 20:44:18

JavaScript的函数闭包使用的相关文章

JavaScript碎片———函数闭包(模拟面向对象)

经过这几天的博客浏览,让我见识大涨,其中有一篇让我感触犹深,JavaScript语言本身是没有面向对象的,但是那些大神们却深深的模拟出来了面向对象,让我震撼不已.本篇博客就是在此基础上加上自己的认知,如有错误,还请见谅. 具体来说实现模拟面向对象主要是利用JavaScript函数闭包这个概念.由于JavaScript中的每一个function都会形成一个作用域,而如果变量声明在这个域中,那么外部是无法直接去访问,要想访问必须new出一个实例来,相当于Java中class.首先让我们来了解一下pr

JavaScript的函数闭包概念

闭包是指有权访问另一个函数作用域中的变量的函数 一.创建闭包的常见的方式: 就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量. //通过闭包可以返回局部变量 function box() { var user = 'Lee'; return function () { //通过匿名函数返回 box()局部变量 return user; }; } alert(box()()); //通过box()()来直接调用匿名函数返回值 var b = box(); alert(b())

javascript匿名函数 闭包

匿名函数 (function(){                console.info("111111111");            })(); var my = (function(){                return "11111111";            })(); 函数里放匿名函数叫闭包 function my(){                return function(){                    retur

每天一个JavaScript实例-使用带有定时器的函数闭包

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>每天一个JavaScript实例-使用带有定时器的函数闭包</title> <style> #redbox{ position:absolute; left:100px;

JavaScript进阶系列01,函数的声明,函数参数,函数闭包

本篇主要体验JavaScript函数的声明.函数参数以及函数闭包. □ 函数的声明 ※ 声明全局函数 通常这样声明函数: function doSth() { alert("可以在任何时候调用我"); } 通过这种方式声明的函数属于Window对象,可以在任何地方调用,即在doSth方法的之前和之后都可以调用. 可以在doSth方法之前调用: doSth(); function doSth() { alert("可以在任何时候调用我"); } 可以在doSth方法之

深入理解javascript原型和闭包(2)——函数和对象的关系 (转载)

深入理解javascript原型和闭包(2)--函数和对象的关系 上文(理解javascript原型和作用域系列(1)--一切都是对象)已经提到,函数就是对象的一种,因为通过instanceof函数可以判断. var fn = function () { }; console.log(fn instanceof Object); // true 对!函数是一种对象,但是函数却不像数组一样--你可以说数组是对象的一种,因为数组就像是对象的一个子集一样.但是函数与对象之间,却不仅仅是一种包含和被包含

JavaScript基础学习之-javascript权威指南--8.6函数闭包

一.什么是闭包? 官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 相信很少有人能直接看懂这句话,因为他描述的太学术. 其实这句话通俗的来说就是:JavaScript中所有的function都是一个闭包.不过一般来说,嵌套的function所产生的闭包更为强大,也是大部分时候我们所谓的“闭包”.看下面这段代码: function a() { var i = 0; function b() { alert(++i); } r

一篇文章把你带入到JavaScript中的闭包与高级函数

在JavaScript中,函数是一等公民.JavaScript是一门面向对象的编程语言,但是同时也有很多函数式编程的特性,如Lambda表达式,闭包,高阶函数等,函数式编程时一种编程范式. function dada() { var a = 1; var b = function() { console.log(a); } return b // b 就是一个闭包函数,因为它能访问dada函数的作用域 } JavaScript的函数也是对象,可以有属性,可以赋值给一个变量,可以放在数组里作为元素

JavaScript匿名函数和闭包

概述 在JavaScript前端开发中,函数与对其状态即词法环境(lexical environment)的引用共同构成闭包(closure).也就是说,闭包可以让你从内部函数访问外部函数作用域.在JavaScript,函数在每次创建时生成闭包.匿名函数和闭包可以放在一起学习,可以加深理解.本文主要通过一些简单的小例子,简述匿名函数和闭包的常见用法,仅供学习分享使用,如有不足之处,还请指正. 普通函数 普通函数由fucntion关键字,函数名,() 和一对{} 组成,如下所示: 1 functi