• 深入理解闭包


    想要理解闭包,首先,要先理解变量的作用域

    1.变量的作用域

    变量的作用域有两种:全局作用域和局部作用域。

    在 javascript 中,声明的函数内部可以获取到声明的全局变量,另一种,从外部无法直接获取到函数内部所声明的变量。 

    var n = 10;
    function fn(){
        var m = 20;//注意是在函数内部声明
        console.log(n);  
    }
    fn();//10
    console.log(m);//error

    这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!

    function fn(){
      n=999;
    }
    fn();
    alert(n); // 999

    2.什么是闭包

    一般的来说,想要从一个函数的外部获取到函数内所声明的变量,直接获取是不可能的!

    还有一种就是,让一个变量持续的存在一个函数内部。(在 javascript 中有一个垃圾回收机制,当一个函数被调用时,会创建一个当前调用函数的执行环境,当这个函数内的代码执行完毕时,这个执行环境会被销毁,同时内部所含有的变量一并被销毁。)

    由于在 Javascript 语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。

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

    闭包的定义:

      1.闭包是指可以访问其所在作用域的函数

      2.闭包是指有权访问另一个函数作用域中的变量的函数

      3.闭包是指在函数声明时的作用域以外的地方被调用的函数

    var name = "The Window";
     var object = {
       name : "My Object",
       getNameFunc : function(){
         return function(){
           return this.name;
         };
       }
     };
     alert(object.getNameFunc()());//The Window
    
    
    var name = "The Window";
    var object = {
      name : "My Object",
      getNameFunc : function(){
        var that = this;
        return function(){
          return that.name;
        };
      }
    };
    alert(object.getNameFunc()());//My Object

    使用闭包注意:

    1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

    2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

    3.IIFE(立即执行函数)

    严格来讲,IIFE并不是闭包,因为它并不满足函数成为闭包的三个条件。但一般地,人们认为IIFE就是闭包,毕竟闭包有多个定义。

    //函数声明语句写法
    function test(){};
    test();
    
    //函数表达式写法
    var test = function(){};
    test();

    但有时需要在定义函数之后,立即调用该函数。这种函数就叫做立即执行函数,全称为立即调用的函数表达式IIFE(Imdiately Invoked Function Expression)

    [注意] javascript 引擎规定,如果 function 关键字出现在行首,一律解释成函数声明语句。

    (function(){ /* code */ }()); 
    (function(){ /* code */ })(); 
    其他写法
    var i = function(){ return 10; }();
    true && function(){ /* code */ }();
    0, function(){ /* code */ }();
    
    !function(){ /* code */ }();
    ~function(){ /* code */ }();
    -function(){ /* code */ }();
    +function(){ /* code */ }();
    
    new function(){ /* code */ };
    new function(){ /* code */ }(); 
  • 相关阅读:
    [LeetCode#91]Decode Ways
    [LeetCode#130]Surrounded Regions
    [LeetCode#84]Largest Rectangle in Histogram
    [LeetCode#179]Largest Number
    [LeetCode#187]Repeated DNA Sequences
    [LeetCode#200]Number of Islands
    [LeetCode#268]Missing Number
    [LeetCode#44]Wildcard Matching
    [LeetCode#128]Longest Consecutive Sequence
    1如何给devexpress的gridview控件绘制全选按钮
  • 原文地址:https://www.cnblogs.com/exhuasted/p/7645751.html
Copyright © 2020-2023  润新知