每天3小时学前端之JS-第18天-闭包3

352 阅读2分钟

此系列体验视频教程

点击观看:哔哩哔哩

闭包

闭包的生命周期

  • 在内部函数定义(不是调用)完成就产生了
  • 将闭包的引用设置为null,彻底清除对闭包的引用,闭包才销毁
/* 
  内部函数定义(不是调用)完成,闭包产生。也就意味着要调用外部函数。
*/
function record() {
  console.dir(inner)
  // 如果是函数表达式定义函数,在此就会产生闭包
  var step = 0
  /* var inner = function () { // 函数表达式定义的函数必须要到这行,函数的赋值完成,才会产生闭包
    return ++step
  }
  console.dir(inner) */
  function inner() {
    return ++step // 延长了函数内部局部变量的生命周期
  }
  return inner
}
var r = record()
console.log(r());
console.log(r());
console.log(r());
console.dir(r)
r = null // 手动将r设置为null,也就是将内部函数的引用关系清除掉,闭包也就被销毁了。
console.dir(r)

闭包的两个作用

  1. 延长了局部变量的生命周期,使局部变量在函数执行之后,仍然存在于内存中
  2. 在函数外部可以操作函数内部的数据

闭包的缺点

内存溢出

// 内存不够、网页崩溃,所剩余的内存不够使用,浏览器就会抛出内存溢出的错误提示
var obj = {}
for (var i = 0; i < 10; i++) {
  obj[i] = Array(10)
}
console.log(obj);

内存泄漏

function fn() {
  var arr = Array(10) // 内存泄漏 内存占用
  return function () {
    return arr.length
  }
}
// 内存泄漏过多就会引起内存溢出
var f = fn()
console.log(f());
f = null

练习

// 1、
var name ='xiaohua'
var obj = {
  name: 'xiaoming',
  getName: function () {
    return function () {
      console.log(name); // 使用的是全局变量,不会产生闭包
    }
  }
}
obj.getName()() // xiaohua

// 2、
var name ='xiaohua'
var obj = {
  name: 'xiaoming',
  getName: function () {
    var name = 'xiaoxiao'
    return function () { // 有闭包
      console.log(name);
    }
  }
}
obj.getName()() // xiaoxiao

// 3、
var name = 'xiaohua'
var obj = {
  name: 'xiaoming',
  getName: function () {
    var name = 'xiaoxiao'
    return {
      fn: function() {
        console.log(name); // xiaoxiao 存在闭包的
        console.log(obj.name); // xiaoming
        console.log(window.name); // xiaohua
      }
    }
  }
}
obj.getName().fn()

// 4、
var name = 'xiaohua'
function fn() {
  var name = 'xiaoxiao'
  return {
    name: 'xiaoming',
    fn2: function () {
      console.log(name); // xiaoxiao 存在闭包
    }
  }
}
fn().fn2()