JS闭包

作者: puxiaotaoc | 来源:发表于2018-08-16 14:38 被阅读0次

一、变量的作用域

  • 变量的作用域分为两种:全局变量和局部变量;
// 函数内部可以直接读取全局变量
    var n = 1;
    function fun1(){
      alert(n);
    }
    fun1(); // 1
// 函数外部无法读取函数内的局部变量
    function fun1(){
      var n = 1;
      alert(n);
    }
    alert(n); // n is not defined
// 函数内部声明变量的时候一定要使用var,否则实际上相当于声明了一个全局变量
    function fun1(){
      n = 1;
    }
    fun1();
    alert(n); // 1

二、闭包的引入

  • 匿名自执行函数实现
    创建匿名自执行函数并立即执行他,由于外部无法引用它内部的变量,因此在执行完后很快会被释放,关键是这种机制不会污染全局对象;
(function(a){
      console.log(a) // 3
 }(3))
  • 读取其他函数的内部变量,是将函数内部和函数外部连接起来的一座桥梁
// 在函数外部访问内部变量n
    function fun1() {
      var n = 1;
      return function() {      
        alert(n);    
      }
    }
    var result = fun1();
    result(); // 1
// getNameFunc的第一个()是属于方法调用,所以this绑定到了object对象,自然this.name为"My Object",但是闭包函数无法访问这个this,它只能访问到全局的this
// 当一个函数作为函数而不是方法调用的时候,这个this关键字引用全局对象
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() {              
          return this.name; // My Object
          // return name; // The Window    
      }  
    };  
    alert(object.name); // My Object
    alert(object.getNameFunc());
var name = "The Window";  
    var object = {    
      name: "My Object",
      getNameFunc: function() {
        var _this = this;              
        return function() {
          return _this.name;     
        } 
      } 
    };  
    alert(object.name); // My Object
    alert(object.getNameFunc()()); // My Object
// 实现封装
// person之外的地方无法访问person内部的变量,只能通过提供闭包的形式来访问
var person = function() {    
      var name = "My Object";
      return {
        getName: function() {
          return name;
        },
        setName: function(val) {
          name = val;
        }
      }
    }
    var person1 = new person(); 
    alert(person1.name); // undefined
    alert(person1.getName()); // My Object
    person1.setName('lili');
    alert(person1.getName()); // lili
// 设置缓存
function db() {
      var data = {};
      return function(key, val) {
        if (val === undefined) {
          return data[key];
        } else {
          return data[key] = val;
        }
      }
    }
    var db = new db();
    console.log(db('x')); // undefined
    console.log(db('x',1)); // 1
    console.log(db('x')); // 1
// 使用自执行函数设置缓存
var db = (function() {
      var data = {};
      return function(key, val) {
        if (val === undefined) {
          return data[key];
        } else {
          return data[key] = val;
        }
      }
    })()
    console.log(db('x')); // undefined
    console.log(db('x',1)); // 1
    console.log(db('x')); // 1
  • 让一些变量的值始终保持在内存中
// 代码中的result实际上就是闭包fun2函数,result一共运行了两次,第一次的值是1,第二次是2,函数fun1的局部变量n一直保存在内存中,并没有在fun1调用后被自动清除,
// 因为fun1是fun2的父函数,而fun2被赋值给了一个全局变量,这导致fun2始终在内存中,而fun2的存在依赖于fun1,因此fun1也始终在内存中,不会在调用结束后被垃圾回收机制回收
// nAdd=function(){n+=1},因为没有在nAdd前面使用var关键字,所以nAdd是一个全局变量,而不是局部变量
// 其次,nAdd的值是一个匿名函数,而这个匿名函数本身也是一个闭包,所以nAdd相当于一个setter,可以在函数外部对函数内部的局部变量进行操作
    function fun1() {
      var n = 1;
      nAdd = function() {
        n += 1;
      }
      return function fun2() {      
        alert(n);    
      }
    }
    var result = fun1();
    result(); // 1
    nAdd();
    result(); // 2

三、闭包的缺陷

  • 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能会导致内存泄露,解决方法是,在退出函数之前,将不使用的局部变量全部删除;
  • 闭包会在父函数外部,改变父函数内部变量的值,所以如果把父函数当作对象使用,把闭包当作它的公用方法,把内部变量当作它的私有属性,这时应小心不能随便改变父函数内部变量的值;

相关文章

  • php之闭包函数(Closure)

    php闭包函数(Closure) JS闭包 js和php闭包使用和区别

  • JS闭包

    JS闭包 闭包练习

  • JS闭包问题(二)

    在之前的JS闭包问题(一)文章中大概介绍了一下JS闭包,同时讲了闭包与变量之间的问题,今天我们继续聊闭包,聊聊闭包...

  • JS闭包大结局(JS闭包系列3)

    在上一篇中再谈JS闭包(JS闭包系列2),我详细的介绍了JS中的变量作用域相关的概念,结合第一节关于JS闭包(JS...

  • JS闭包入门

    最近有看到朋友的面经里提到的JS闭包的问题,就想研究研究,以下是我对JS闭包的简单理解。 到底什么是JS闭包? 定...

  • 学习JavaScript闭包和作用域笔记

    JS JavaScript闭包和作用域 闭包 JavaScript高级程序设计中对闭包的定义:闭包是指有权访问另外...

  • 再谈JS闭包(JS闭包系列2)

    这篇文章,来继续谈谈Javascript闭包的剩余问题。因为在上一篇文章中关于JS闭包(JS闭包系列1)主要简单的...

  • 简单的聊一下闭包

    js中的闭包 闭包是学习js中永远也绕不过去的一个坎,那么,今天我们就去一段简单的代码开始聊一聊闭包 什么是闭包 ...

  • 浅谈闭包

    js中的闭包 闭包是学习js中永远也绕不过去的一个坎,那么,今天我们就去一段简单的代码开始聊一聊闭包 什么是闭包 ...

  • 闭包??

    什么闭包,闭包有什么用?http://js.jirengu.com/pogadikofa/1/闭包是在某个作用域内...

网友评论

    本文标题:JS闭包

    本文链接:https://www.haomeiwen.com/subject/jemnbftx.html