作用域指程序中定义变量的区域,它决定了当前执行代码对变量的访问权限。
最外层的作用域,第一次执行代码的默认环境,一直存在,在全局作用域中的变量,可以被所有的函数访问。
在函数被定义时生成的作用域,函数作用域内的全部变量都可以在整个函数的范围内使用及复用,在这个函数作用域中嵌套的作用域也可以使用。
当可执行代码内部访问变量时,会先查找本地作用域,如果找到目标变量即返回,否则会去父级作用域继续查找,一直找到全局作用域。我们把这种作用域的嵌套机制,称为作用域链。具体情形如下:
- 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的变量标记为失效变量并将之清除从而释放内存。但是在某些情况下,当一块内存不再被应用程序使用的时候,由于某种原因,这块内存没有返还给操作系统或者内存池,这种情况就叫做内存泄漏。内存泄漏可能会导致应用程序卡顿或者崩溃。
引起内存泄露的情况有哪些:
因此,闭包虽然好用,但是可以不用的时候尽量不要用,用了的话要及时清除。