1. 变量作用域
变量作用域两种:全局变量、局部变量。
- 全局变量:函数外声明的变量,称为全局变量
- 局部变量:函数内部使用var声明的变量,称为局部变量
在JS中(ES5),只有函数作用域,没有块级作用域!!!也就是说,if/for等有{}的结构体,并不能具备自己的作用域。(ES6提供了块级作用域,let、const)
所以,函数外部不能访问函数内部局部变量(私有属性)。因为,函数内部的变量,在函数执行完毕以后,就会被释放掉。(涉及js垃圾回收机制)
2. 如何从外部读取函数内部的变量?
function func1(){
var a = 12
function func2(){ // func2是一个闭包
alert(a)
}
return func2
}
- js链式作用域:子对象会一级一级向上寻找所有父对象的变量,反之不行。
- func2可以读取func1内的变量,只要将func2作为返回值,就可以在func1外部读取func1内部变量
3.闭包的概念
能够读取其他函数内部变量的函数;
或简单理解为定义在一个函数内部的函数,内部函数持有外部函数内变量的引用。
4.闭包的用途
-
读取函数内部的变量
-
让这些变量的值始终保持在内存中。不会在func1调用后被自动清除。
func1是func2的父函数,func2被赋给了一个全局变量。因此,func2始终存在内存中,func2的存在依赖func1,因此func1也始终存在内存中,不会在调用结束后,被垃圾回收机制回收。垃圾回收机制:(js内存管理的主要概念-可达性)
1、可达性即那些以某种方式可访问或可用的值,它们被保证存储在内存中。
2、一般来说没有被引用的对象就是垃圾,就是要被清除。 有个例外如果几个对象引用形成一个环,互相引用,但“根”访问不到它们,这几个对象也是垃圾,也要被清除。即可达性, -
方便调用上下文的局部变量。利于代码封装。
5.闭包的理解
function init() {
var name = "Chrome"; //创建局部变量name和局部函数alertName
function alertName() { //alertName()是函数内部方法,是一个闭包
alert(name); //使用了外部函数声明的变量,内部函数可以访问外部函数的变量
}
alertName();
}
init();
- 词法作用域中使用的域,是变量在代码中声明的位置所决定的(全局,函数,块级)。嵌套的函数可以访问在其外部声明的变量。
function outFun(){
var name = "Chrome";
function alertName(){
alert(name);
}
return alertName; //alertName被外部函数作为返回值返回了,返回的是一个闭包
}
var myFun = outFun();
myFun();
- 闭包有函数+它的词法环境;词法环境指函数创建时可访问的所有变量。
- myFun引用了一个闭包,闭包由alertName()和闭包创建时存在的“Chrome”字符串组成。alertName()持有了name的引用,myFun持有了alertName()的访问,因此myFun调用时,name还是处于可以访问的状态。
function add(x){
return function(y){
return x + y;
};
}
var addFun1 = add(4);
var addFun2 = add(9);
console.log(addFun1(2)); //6
console.log(addFun2(2)); //11
- add接受一个参数x,返回一个函数。这个返回的函数的参数是y,返回x+y
- add是一个函数工厂,传入一个参数,就可以创建一个参数和其他参数求值的函数。
- addFun1和addFun2都是闭包。他们使用相同的函数定义,但词法环境不同,addFun1中x是4,后者是9
相关文章
对JS闭包的理解及常见应用场景
前端面试:谈谈 JS 垃圾回收机制
ES6 变量作用域与提升:变量的生命周期详解
关于JavaScript中的闭包及应用场景
网友评论