【JavaScript回顾】闭包

  

什么是闭包?

  闭包是指有权访问另一个 函数作用域中的变量的函数(也就是说,你这个函数用到的变量另外一个域的就算闭包)

  

 <script>
        function f1() {
            var age = 10;

            //这个函数就是闭包
            function f2() {
                return age;
            }
            return f2;
        }

        alert(f1()());

    </script>

    在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

闭包与变量 (这里需要注意的)

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

如上代码,如果调用以后所有的值都会是10,而不是我们预想的1-10,这是因为每个函数的作用域链中 都保存着 createFunctions()函数的活动对象,所以它们引用的都是同一个变量 i。当 createFunctions()函数返回后,变量 i 的值是 10,此时每个函数都引用着保存变量 i 的同一个变量 对象,所以在每个函数内部 i 的值都是 10。但是,我们可以通过创建另一个匿名函数强制让闭包的行为 符合预期,如下所示。

 <script>
        function createFunctions() {
            var result = new Array();
            for (var i = 0; i < 10; i++) {
                result[i] = function (num) {
                    return function () {
                        return num;
                    }
                }(i);//这里直接调用了闭包(function(num)这个函数),
                    //所以result存的是function(){return num;}这个函数
                //当然,也可以直接调用,那么下面就不用写()了:createFunctions()[8]
            }
            return result;
        }

        alert(createFunctions()[8]());
    </script>

  在重写了前面的 createFunctions()函数后,每个函数就会返回各自不同的索引值了。在这个版 本中,我们没有直接把闭包赋值给数组,而是定义了一个匿名函数,并将立即执行该匿名函数的结果赋 给数组。这里的匿名函数有一个参数 num,也就是终的函数要返回的值。在调用每个匿名函数时,我 们传入了变量 i。由于函数参数是按值传递的,所以就会将变量 i 的当前值复制给参数 num。而在这个 匿名函数内部,又创建并返回了一个访问 num 的闭包。这样一来,result 数组中的每个函数都有自己 num 变量的一个副本,因此就可以返回各自不同的数值了。

闭包中的this对象

  我们知道,this 对象是在运行时基于函数的执 行环境绑定的:在全局函数中,this 等于 window,而当函数被作为某个对象的方法调用时,this 等于那个对象。不过,匿名函数的执行环境具有全局性,因此其 this 对象通常指向 window①。但有时候 由于编写闭包的方式不同,这一点可能不会那么明显。下面来看一个例子

 <script>
        var name = "Windows";

        var obj = {
            name: "closure",
            getName: function () {
                return function () {
                    return this.name;
                }
            }
        }
        alert(obj.getName()());
    </script> 

  这个例子该死的正确的答案居然是:Windows, 搞了吧!!! Why?

  

  每个函数在被调用时都会自动取得两个特殊变量:this 和 arguments。内部函数在搜索这两个变量时,只会搜索到其活动对象为止,因此永远不可能直接访问外部函数中的这两个变量。不过,把外部作用域中的 this 对象保存在一个闭包能够访问 到的变量里,就可以让闭包访问该对象了,如下所示

 <script>
        var name = "Windows";

        var obj = {
            name: "closure",
            getName: function () {
                var that = this;
                return function () {
                    return that.name;
                }
            }
        }
        alert(obj.getName()());
    </script>

  在定义匿名函数之前,我们把 this 对象赋值给了一个名叫 that 的变量。而在定义了闭包之后,闭包也可以访问这个变量,因为它是我们 在包含函数中特意声名的一个变量。即使在函数返回之后,that 也仍然引用着 object,所以调用 object.getNameFunc()()就返回了"My Object"。

  来看下三种不同的调用getName的方式的不同结果:

        alert(object.getName());
        alert((object.getName)());
        alert((object.getName = object.getName)());    

  返回值:1.closure

      2.closure

      3.Windows

  

  第一行代码跟平常一样调用了 object.getName(),返回的是"closure",因为 this.name 就是 object.name。第二行代码在调用这个方法前先给它加上了括号。虽然加上括号之后,就好像只 是在引用一个函数,但 this 的值得到了维持,因为 object.getName 和(object.getName)的定义 是相同的。第三行代码先执行了一条赋值语句,然后再调用赋值后的结果。因为这个赋值表达式的值是 函数本身,所以 this 的值不能得到维持,结果就返回了"Windows"。

   当然,你不大可能会像第二行和第三行代码一样调用这个方法。不过,这个例子有助于说明即使是 语法的细微变化,都有可能意外改变 this 的值。

闭包缺点

  除了以上那么恶心的东西之外...最大的缺点还是暂用内存比较大,如果不是必要的还是慎用。

时间: 2024-12-27 20:59:35

【JavaScript回顾】闭包的相关文章

HTML5移动开发之路(29)—— JavaScript回顾4

本文为 兄弟连IT教育 机构官方 HTML5培训 教程,主要介绍:HTML5移动开发之路(29)-- JavaScript回顾4 一.变量的作用域 JavaScript脚本的执行过程分为两个阶段: 第一阶段,js引擎()先扫描整个javascript代码.当碰到<script>时,会先创建一个全局的活动对象,将<script>中出现的变量的声明,函数的定义保存在活动对 象里面.如果碰到函数,则创建对应的局部活动对象,将函数内部的变量的声明及函数的定义保存在该活动对象里面. 第二阶段

HTML5移动开发之路(30)—— JavaScript回顾5

本文为 兄弟连IT教育 机构官方 HTML5培训 教程,主要介绍:HTML5移动开发之路(30)-- JavaScript回顾5 一.查找 第一种方式:依据id查找 var obj = document.getElementById(id);   //document是HTMLDocument的实例 [html] view plain copy print? <html> <head> <script> function f1(){ var obj = document

HTML5移动开发之路(27)—— JavaScript回顾2

本文为 兄弟连IT教育 机构官方 HTML5培训 教程,主要介绍:HTML5移动开发之路(27)-- JavaScript回顾2 JavaScript面向对象基础知识 1.如何定义一个类,使用如下语法来创建一个类 [javascript] view plain copy print? function Person(name, age){ //习惯上第一个字母大写 //this修饰的变量称为属性 this.name = name; this.age = age; //如果属性值是一个函数,则这个

HTML5移动开发之路(28)—— JavaScript回顾3

本文为 兄弟连IT教育 机构官方 HTML5培训 教程,主要介绍:HTML5移动开发之路(28)-- JavaScript回顾3 一.基本数据类型 number:数字类型 string:字符串 (注意s小写:string是基本类型) boolean:布尔类型   //前三个都有对应的包装类 null:空类型 undefined:未定义类型 测试一: [html] view plain copy print? <html> <!--基本类型测试--> <head> <

javascript 关于闭包的知识点

javascript 关于闭包的认识 概念:闭包(closure)是函数对象与变量作用域链在某种形式上的关联,是一种对变量的获取机制. 所以要大致搞清三个东西:函数对象(function object).作用域链(scope chain)以及它们如何关联(combination) 首先要建立一个印象,在js中,几乎所有的东西可以看作对象,除了null和undefined.比如常用的数组对象.日期对象.正则对象等. var num = 123; // Number var arr = [1,2,3

javascript Closure 闭包

引用自 http://www.cnblogs.com/mguo/archive/2013/06/19/3143880.html /*一.变量的作用域要理解闭包,首先必须理解Javascript特殊的变量作用域.变量的作用域无非就是两种:全局变量和局部变量.Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量.*/ var n=999; function f1(){ alert(n); } f1(); // 999//另一方面,在函数外部自然无法读取函数内的局部变量. funct

JavaScript中闭包实现的私有属性的getter()和setter()方法

注意: 以下的输出都在浏览器的控制台中 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>闭包</title> </head> <body> <script type="text/javascript"> /** * 利用闭包实现 * 这个函数给对象o增加了属性存储器方法 * 方法名称为ge

javascript学习-闭包

javascript学习-闭包 1.什么是闭包 大多数书本中对闭包的定义是:“闭包是指有权访问另一个函数作用域中的变量的函数.”.这个概念过于抽象了,对初学者而言没啥帮助.好在<Javascript忍者秘籍>5.1中给了一个例子来进一步的解释了什么是闭包: var outerValue= 'ninja'; var later; function outerFunction() { var innerValue = "samurai"; function innerFunct

两个示例介绍JavaScript的闭包

JavaScript的闭包有两个用途:一个是访问函数内部的变量:另一个是让变量的值在作用域内保持不变.函数是JavaScript 中唯一有作用域的对象,因此JavaScript的闭包依赖于函数实现,下面结合两则示例对JavaScript的闭包做简单说明. 1. 访问函数内部的变量 JavaScript中没有严格意义上的类,所以我们常用函数来模拟类.我们可以像下面这样模拟一个Counter类,并在其中定义一个count私有变量: 在JavaScript中,函数可以访问其外部定义的变量,而外部不能访

JavaScript基础–闭包

JavaScript基础–闭包 理解闭包的概念对于学习JavaScript至关重要,很多新手(包括我)开始学习闭包时,都会感觉似懂非懂,之前看了一些资料,整理了闭包的一篇博客,若有疏忽与错误,希望大家多多给意见. 概述 理解闭包的概念前,建议大家先回想一下JS作用域的相关知识,如果有疑问的同学,可以参考:JavaScript基础–作用域.闭包的定义如下: Closure is when a function is able to remember and access its lexical s