zoukankan      html  css  js  c++  java
  • javascript 中的闭包

    理解必包三个基本事实

    1. JS允许你引用在当前函数以外定义的变量。

    ex:

    function makeSandwich(){

    var magicIngredient = “peanut butter”;

    function make(filling){

    return magicIngredient +’ and ‘+ filling;

    }

    return make(‘jelly’);

    }

    makeSandwich();

     

    2. 即使外部函数已经返回,当前函数仍然可以引用在外部函数所定义的变量。这意味着,你可以返回一个内部函数。

    ex:

    function mkSandwich(){

    var magicIngredient = ‘peanut butter’;

    function make (filling){

    return magicIngredient +’ and ‘+filling;

    }

    return make;

    }

    var mk =  mkSandwich();

    mk(‘jelly’);

    mk(‘bananas’);

    mk(‘marshmallows’);

     

    Javascript函数值在内部存储它们可能会引用的定义在其封闭作用域的变量。

    那些在其所涵盖的作用域内跟踪变量的函数被称为闭包。

    make函数就是一个闭包,引用两个外部变量: magicIngredient和filling。

    函数可以引用在其作用域内的任何变量,包括参数和外部函数变量。

    ex: 

    function mkSandwich(magicIngredient){

    function make(filling){

    return magicIngredient + ’and’ + filling;

    }

    return make;

    }

    var mk = mkSandwich(‘peanut butter’);

    mk(‘jelly’);

    mk(‘cheese’);

    var mkspeical = mkSandwich(’turkey’);

    mkspeical(’swiss’);

    mkspeical(‘provolone’);

     

    构建闭包的字面量语法-函数表达式

    ex:

    function mkSandwich(magicIngredient){

    return function(filling){

    return magicIngredient +’  and ‘+ filling;

    }

    }

     

    3. 必包可以更新外部变量的值。实际上必包存储的事外部变量的引用,而不是它们值的副本。

    ex:

    function box(){

    var val = undefined;

    return {

    set : function(newVal){

    val = newVal;

    },

    get : function(){

    return val;

    },

    type : function(){

    return typeof val;

    },

    }

    }

    var boxdemo = box();

    boxdemo.type();

    boxdemo.set(998);

    boxdemo.get();

    boxdemo.type();

     

     

    要搞清楚闭包,首先要知道javascript中的作用域.

     

    什么是作用域,你可以简单的理解成当前上下文环境.

     

    javascript 中的作用域有2种

    属于全局作用域.

    属于局部作用域

     

    全局作用域:

    比如我们在浏览器端编写的 javascript 代码,

    1

    var name=‘test’;

    我们直接定义了一个变量name ,那么这个变量当前作用域就是全局,对于浏览器端全局就是window

    更确切的说,name 是window 对象的一个属性.

    1

    2

    3

    console.log(window.name); //test

    console.log(name); //test

    console.log(this.name); //test

     

    上面三种输出方法,结果都是一样的,因为当前作用域就是window对象,this指向当前作用域.

     

     

    局部作用域:

    此类作用域是针对javascript中函数的作用域.

    是指在函数内部定义的变量,如下:

    1

    2

    3

    4

    function test(){

        var name=‘yijiebuyi’;

        alert(this.name);

    }

     

    上面 name 是一个局部变量,定义在函数内部,所以它的作用域就是此函数内部可以访问.

    alert(this.name);  this 指向当前作用域,因为在函数内部,所以指函数作用域.

     

    如果函数外部  alert(name); 将会报错,返回 undefined

    但是 函数内部可以访问函数外部作用域,如下:

    1

    2

    3

    4

    var name=‘test’;

    function test(){

       alert(name); //test

    }

    上面的代码没有问题,函数内部作用域可以访问全局作用域,(或者简单理解成 函数内部作用于可以访问它父级作用域)

     

    既然函数可以访问父作用域变量,而且函数是一等公民,可以当做参数,返回值等.

    那么问题来了:

    1

    2

    3

    4

    5

    6

    function test(){

        var name=‘yijiebuyi’;

        return function(){

            console.log(name);

        }

    }

    1

    2

    var rtn=test();

    rtn(); //yijiebuyi

    我们上面运行 rtn() ,得到 yijiebuyi,说明了2个问题:

    1.函数确实是头等公民,可以当参数,可以当返回值.

    2.函数可以访问它的父作用域,因为成功输出了 yijiebuyi

     

    我们再换一个思路:

    如果我不返回这个匿名函数,但是我想得到 test 函数中的 name 属性值,怎么办?

    好像不行,办不到,只能返回一个函数来获取 test 函数内部变量了,其实这个过程就是 一个典型的闭包!

     

    我们在返回匿名函数的时候并没有返回 var name=‘yijiebuyi’  但是运行 rtn 函数却得到了 name 属性值.

     

    所以:

    闭包的作用就是:把函数内部私有变量暴露出来. (暴露作用域)

    闭包如何实现:函数里面返回一个函数.

     

    这个返回函数自动带上了父函数所在的作用域,所以可以访问其内部变量,

    也正是因为闭包的存在,导致父函数执行完成后并没有被垃圾回收,它的作用域内的变量都将保存在内存中供闭包使用.

  • 相关阅读:
    IOS中延迟执行的几种方法
    Xcode6中如何去掉默认的Main.storyboard
    IOS7.0 UILabel实现自适应高度的新方法
    UITabBarController常见代理方法的使用
    Infopath 2010 接收SQL Server数据
    olsr学习之一:Ubuntu10.04下ns2-allinone-2.34安装方法
    常用工具遇到的错误以及解决方法
    笔记本电脑选购个人的一些浅见
    嵌入式题目集锦
    关于网络传输字节顺序的问题: hton? or ntoh?
  • 原文地址:https://www.cnblogs.com/papajia/p/4498218.html
Copyright © 2011-2022 走看看