• 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 属性值.

     

    所以:

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

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

     

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

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

  • 相关阅读:
    js截取字符串区分汉字字母代码
    List 去处自定义重复对象方法
    63. Unique Paths II
    62. Unique Paths
    388. Longest Absolute File Path
    41. First Missing Positive
    140. Word Break II
    139. Word Break
    239. Sliding Window Maximum
    5. Longest Palindromic Substring
  • 原文地址:https://www.cnblogs.com/papajia/p/4498218.html
Copyright © 2020-2023  润新知