闭包相关概念

  几天没有更新,这两天使周末,给大家整理了一几篇东西,有关于作用域的,闭包的,还有递归的,闭包和递归,对于大部分初次接触编程的人来说还是有些难度的,昨天,花了一点时间给大家整理了一下,今天,给大家上传上来,让大家看看,部分属于个人观点,如有错误,欢迎指出

  这一篇给大家讲讲什么是闭包,闭包在很多语言中都是有的,Java,C#等都是有的,这里给大家讲讲JS中的闭包

1. 闭包

闭包的含义就是闭合,抱起来。简单的的来说就是一个具有封闭功能与包裹功能的一个结构,所谓的闭包就是 有一个具有封闭的对外不公开的包裹结构,或空间

在JS中函数可以构成闭包,一般函数是一个代码结构的封闭结构,即包裹的特性,同事根据作用域规则 只允许函数访问外部的数据,外部无法访问函数内部的数据,即封闭的对外不公开的特性,因此说函数可以构成闭包

1.1. 闭包要解决什么问题

  1. 闭包不允许外界访问
  2. 要解决的问题就是间接访问该数据

函数就可以构成闭包,要解决的问题就是访问到函数内部的数据

    function foo () {
        var num = 123;
        return num;
    }
    var res = foo();
    console.log( res ); // => 123
  1. 这里的确是访问到函数中的数据
  2. 但是该数据不能第二次访问. 因为第二次访问的时候又要调用一次 foo, 表示又有一个新的 num = 123 出来了

在函数内的数据, 不能直接在函数外被访问, 那么再函数内如果定义一个函数, 那么再这个内部函数中是可以直接访问的

    function foo() {
        var num = Math.random();
        function func() {
            return num;
        }
        return func;
    }
    var f = foo();
    // f 可以直接访问这个 num
    var res1 = f();
    var res2 = f();

练习:

    function foo () {
        var o = { name: ‘jim‘ };
        return function () {
            return o;
        }
    }

1.2. 函数科里化(高阶函数)

定义一个函数, 该函数返回一个函数, 那么在调用的时候

    function foo() {
        function func() {
        }
        return func;
    }
    foo()()

JavaScript 模式

    function color( r, g, b ) {
        // ...
    }
    =>
    color( 255, 0, 0 )
    function color ( r ) {
        return function color( g ) {
            return color( b ) {
            }
        }
    }
    color( 255 )( 0 )( 0 )

1.3. 如何获得超过一个数据

    function foo () {
        var num1 = Math.random();
        var num2 = Math.random();

        return {
            num1: function () {
                return num1;
            },
            num2: function () {
                return num2;
            }
        }
    }

1.4. 如何完成读取一个数据和修改这个数据

    function foo () {
        var num = Math.random();
        return {
            get_num: function () {
                return num;
            },
            set_num: function ( value ) {
                num = value;
            }
        }
    }

1.5. 基本的闭包结构

一般闭包的问题就是要想办法简介的获得函数内数据的使用权,那么我们可以总结出一个基本的使用模型

  1. 写一个函数,函数内定义一个新函数,返回新函数,用新函数获得函数内的数据
  2. 写一个函数,函数内定义一个对象,对象中绑定多个函数(方法),返回对象,利用对象的方法访问函数内的数据

1.6. 闭包的基本语法

闭包是为了实现 具有私有访问空间的 函数

  1. 带有私有访问数据的对象
    function Person() {
        this.name = ‘张三‘;
        // setName( ‘‘ )
    }
    // 所谓的私有数据, 就是说只有函数内部可以访问的数据, 或对象内部的方法可以访问的数据

    // 1  最简单的实现方式
    function createPerson() {
        var __name__ = "";
        return {
            get_Name: function () {
                return __name__;
            },
            set_Name: function ( value ) {
                // 如果不姓张就报错
                if ( value.charAt( 0 ) === ‘张‘ ) {
                    __name__ = value;
                } else {
                    throw new Error( ‘姓氏不对, 不能取名‘ );
                }
            }
        };
    }
    // 2
  1. 带有私有数据的函数

     var func = function () {}
     function func () {}
    
     var foo = (function () {
         // 私有数据
         return function () {
             // 可以使用私有的数据
    
         };
     })();
    

1.7. 闭包的性能问题

函数执行需要内存,那么函数中定义的变量,会在函数执行结束后自动护手,凡是因为闭包结构,被引出的数据, 如果还有变量引用这些数据的话,那么这些数据就不会被回收。

因此在使用闭包的时候如果不使用某些数据了,一定要赋值一个 null

    var f = (function () {
        var num = 123;
        return function () {
            return num;
        };
    })();

    // f 引用着函数, 函数引用变量 num
    // 因此在不使用该数据的时候, 最好写上
    f = null;

1.8. 闭包的练习

1.8.1. 对象模型

    function foo() {
        // 私有数据
        return {
            method: function ( ) {
                // 操作私有数据
            }
        }
    }

1.8.2. 函数模型

可以实现一个函数的二次加工

    function foo () {
        // 私有数据
        return function () {
            // 可以操作私有数据
        }
    }
    var func = foo();
    与下面这个正常的区别在于,自己有一个私有的数据
    var fun = function () {

    };

我们还将这种带有带有私有数据的函数模型称作带有缓存功能的函数

1.8.3. 沙箱模式(闭包应用的一个典范)

1.8.3.1. 沙箱的概念

沙盘与盒子,就可以在有一个小小的空间内模拟现实世界,特点是执行的效果与现实世界一模一样,但是只在沙箱中模拟与现实无关

1.8.3.2. 沙箱模式

沙箱模式就是在一个自调用的函数,代码写到函数中一样会执行,但是不会与外界有任何影响

例如在JQ中

(function () {

var jQuery = function () {
    // 所有的算法
}

// ....
// ....
jQuery.each = function () {}

window.jQuery = window.$ = jQuery;

})();

$.each( ... )

1.8.4. 带有缓存功能的函数(这也是沙箱)

以 斐波那契 数列为例

    var fib = (function () {

        var data = [ 1, 1 ];

        return function ( n ) {
            var v = data[ n ];
            if ( v === undefined ) {
                v = fib( n-1 ) + fib( n-2 );
                data[ n ] = v;
            }
            return v;
        };
    })();
时间: 2024-08-01 17:47:20

闭包相关概念的相关文章

Python UnboundLocalError和NameError错误根源解析

如果代码风格相对而言不是那么的pythonic,或许很少碰到这类错误.当然并不是不鼓励使用一些python语言的技巧.如果遇到这这种类型的错误,说明我们对python中变量引用相关部分有不当的认识和理解.而这又是对理解python相关概念比较重要的.这也是本文写作的原因. 本文为理解闭包相关概念的做铺垫,后续会详细深入的整理出闭包相关的博文,敬请关注. 1.案例分析 在整理闭包相关概念的过程中,经常发现UnboundLocalError和NameError这两个错误,刚开始遇到的时候可能很困惑,

折腾自己的js闭包(二)

前面我大致探讨了js里的闭包的相关概念,那么,到底在什么时候用它最好呢?存在即真理,只不过以前没发现它而已,先来看看下面的这几个用途吧 一.我首先想到的就是从函数外面访问它的内部变量,从而达到自己的一些目的,还避免了设定为全局变量的全局变量污染,例如如下这个封装: var person = function(){ //变量作用域为函数内部,外部无法访问 var name = "default name"; return { getName : function(){ return na

JS 中闭包的变量 闭包与this

闭包与变量: 作用域链的一个副作用,闭包只能取得包含函数中任何变量的最后一个值.别忘了闭包所保存的是整个变量对象,而不是某个特殊的变量. function fn1(){ //创建一个数组 var arr = new Array(); //为数组赋值,此时i是保存在fn1 这个作用域中 for (var i = 0; i <10; i++) { arr[i] = function(){ return i } } return arr; } var fs = fn1(); for (var i =

多角度了解Javascript闭包

javascript的闭包是非常有用的特性,利用它可以实现很多功能,在学习闭包的过程中也想分享自己的一些理解和总结,于是写了此文. 闭包是什么?  ( 相关概念:匿名函数,执行环境,作用域链,变量对象,活动对象,this对象,内存泄露). 闭包(closure):有权访问另一个函数作用域中的变量的函数: 匿名函数(anonymous function):创建一个函数并将它赋值给变量functionName; 执行环境(execution context):定义了变量和函数访问其他数据和决定它们各

Javascript中Closure及其相关概念

我相信学过Javascript这门语言的程序员应该都对Closure这个概念有所了解,然而网上以及各种Javascript书籍里面对Closure这个概念的定义有各种说法.我本人觉得很多地方对Closure这个概念的定义都是片面的,目前看到的比较全面准确的定义应该是Wikipedia上面的定义了,但是Wikipedia上面的定义不是很好理解. 我通过网上查阅了些资料后结合Wikipedia的定义,下面给出我自己对Closure这个概念的理解. 要想正确理解闭包必须要先对一些概念有所了解: 非本地

初步学习JS中的闭包

JS高级程序设计(3rd)中对闭包的定义就是一句话,首先闭包是一个函数,怎样的函数呢?有权访问另一个函数作用域中的变量 的函数.而创建闭包的常见方式就是在一个函数的内部创建另一个函数,就是嵌套函数. 闭包会涉及到的点主要有 ①     作用域链(这个原理让我们明白内部嵌套的函数是能够访问外部父函数里定义的变量的,而对于嵌套函数来说引用了非自己作用域内定义的这些变量通常又被称为自由变量) ②     函数执行的机制(这个又涉及到执行环境execution context ,环境栈(注意环境栈的底部

理解运用JS的闭包、高阶函数、柯里化

一.闭包 1. 闭包的概念 闭包与执行上下文.环境.作用域息息相关 执行上下文 执行上下文是用于跟踪运行时代码求值的一个规范设备,从逻辑上讲,执行上下文是用执行上下文栈(栈.调用栈)来维护的. 代码有几种类型:全局代码.函数代码.eval代码和模块代码:每种代码都是在其执行上下文中求值. 当函数被调用时,就创建了一个新的执行上下文,并被压到栈中 - 此时,它变成一个活动的执行上下文.当函数返回时,此上下文被从栈中弹出 function recursive(flag) { // Exit cond

关于JS闭包

摘自吴留坡<原来JavaScript的闭包是这么回事!> 一.相关概念 1.执行上下文 在执行JS代码时候的运行环境称为执行上下文.包括:全局代码--首次执行代码的默认环境:函数代码--每当执行流程进入函数体时. 执行上下文即当前代码的执行环境或作用域. 2.执行过程 全局:启动程序后,从全局执行上下文开始,在全局执行上下文中声明的变量为全局变量 函数体:调用函数时,JS创建一个本地执行上下文--本地执行上下文拥有自己的变量集,即函数的局部变量--新的执行环境被抛到执行栈上. (执行栈为用于跟

Javascript学习日志(三):闭包

说实话,前面一节的原型和原型链在当初学的时候并没有很头疼,对着高级编程第三版撸了几遍就理解透了,闭包这一节真的挺头疼的,很惭愧,看了差不多十来遍吧,还翻看了网上的其他博客和解释文档,五花八门的表达方式,虽然核心思想都一致,但是实在是不能做到自己的理解,后来结合函数作用域链,好不容易有点开窍,趁着热乎劲儿,赶紧写下来,感兴趣的可以参考一下. 闭包:高级编程上面的解释是指有权访问另一个函数作用域中的变量的函数,(是一个函数): 创建闭包的常见方式,就是在一个函数内部创建另一个函数. 在理解闭包之前,