作用域与闭包

本文详细介绍了JavaScript中的作用域概念,包括全局作用域、函数作用域和词法作用域,并探讨了作用域链的工作原理。接着,讲解了闭包的定义、特性及其在内存管理中的角色,通过示例展示了闭包如何保护变量并实现模拟私有属性。同时,提到了闭包可能导致的内存问题,如内存溢出和内存泄漏,强调了合理使用闭包的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作用域

作用域指程序中定义变量的区域,它决定了当前执行代码对变量的访问权限。

全局作用域

最外层的作用域,第一次执行代码的默认环境,一直存在,在全局作用域中的变量,可以被所有的函数访问。

函数作用域

在函数被定义时生成的作用域,函数作用域内的全部变量都可以在整个函数的范围内使用及复用,在这个函数作用域中嵌套的作用域也可以使用。

作用域链

当可执行代码内部访问变量时,会先查找本地作用域,如果找到目标变量即返回,否则会去父级作用域继续查找,一直找到全局作用域。我们把这种作用域的嵌套机制,称为作用域链。具体情形如下:

function fun1(a) {
  var b = a+1;
  function fun2(c) {
    console.log( a, b, c );
  }
  fun2(b+1);
}
fun1(1); // 1 2 3 

不难看出,在函数fun2中,找不到变量a和变量b,因此它一层层作用域向上查找,最终找到了变量a,b。

词法作用域

词法作用域也就是在词法阶段定义的作用域,是由你在写代码时将变量和块作用域写在哪里来决定的,意味着函数的作用域在函数被定义的时候就已经确定了,和他在哪里执行没有关系。

var value = 1;
function fun() {
  console.log(value);
}
function fun2() {
  var value = 2;
  fun();        //函数是在这一行被定义的。
}
fun2();//输出的是2

闭包

官方说闭包就是指有权访问另一个函数作用域中的变量的函数。MDN 对于闭包的解释是一种特殊的对象。它由两部分构成:函数,以及创建该函数的环境。环境由闭包创建时在作用域中的任何局部变量组成。我的理解是闭包就是函数内部定义的函数,被返回了出去并在外部调用。由于函数使用了外部作用域中的某些变量,因此当外部作用域释放时,这些变量因为要被闭包所使用,因此被保护了起来。

function fun1() {
  var a = 1;
  function fun2() {
    console.log(a);
  }
  return fun2;
}
var a = fun1();
a();

闭包变量存储的位置

闭包变量存储于堆内存之中。

闭包的应用场景

一般用于保护某些变量。也可用来模拟私有属性和柯里化函数。

模拟私有属性

function getPersonMessage () {
  var _name = '哈哈哈';
  var _sex = '男';
  var _age = 20;
  return function () {
    return {
      getName: function () {return _name;},
      getSex: function() {return _sex;},
      getAge: function() {return _age;},
    };
  };
}
var person = getPersonMessage()();
person.getName(); // 哈哈哈
person.getAge(); // 20
person.getSex(); // 男
person._name; // undefined

闭包的缺陷

内存溢出

当程序运行所需的内存超出了剩余可分配的内存时,就会产生内存溢出,是一种程序运行出现的错误。                                                                                                                                             

内存泄露

什么是内存泄漏?

js内部的垃圾回收机制是引用计数收集,即当内存中的一个变量被引用一次,计数就加一。垃圾回收机制会以固定的时间轮询这些变量,将计数为0的变量标记为失效变量并将之清除从而释放内存。但是在某些情况下,当一块内存不再被应用程序使用的时候,由于某种原因,这块内存没有返还给操作系统或者内存池,这种情况就叫做内存泄漏。内存泄漏可能会导致应用程序卡顿或者崩溃。

引起内存泄露的情况有哪些:

  1. 意外的全局变量(写了var的是局部变量,没写var的是全局变量)
  2. 没有及时清理的计时器和回调函数
  3. 闭包                                            

因此,闭包虽然好用,但是可以不用的时候尽量不要用,用了的话要及时清除。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值