学习javascript的时候,闭包总是一个难点。发现自己比较笨,所以决定要养成写博客的习惯,也许这样才不会把学到的知识丢掉。因为有时候想明白这个闭包的东西了,但是时间一久就会忘。
作用域
//window
var num = 10;
function changeNum(){
var myNum = 90;
function cha(){
var temNum = myNum;
myNum = num;
num = temNum;
}
cha();
}
changeNum();
上面代码中,num变量就是全局变量,方法changeNum()内部的变量都是局部变量。而且方法内部可以访问num,但是changeNum()之外不能访问myNum.这样就说明他们有个自己的作用域。
执行环境作用域链
var nameStr = "I am window";
function fun(){
var nameStr = "I am fun";
return function(){
console.log(nameStr);
}
}
var f = fun();
f();
每个函数都会有它的执行环境,当执行到一个函数时,就会将其环境推入执行环境栈中,函数执行完后,再将其弹出,返回到之前的执行环境。
比如以上代码,当执行到var f = fun();的时候,会将fun()方法的执行环境推入执行环境栈中,当fun()执行完后,回到之前的执行环境,也就是window中继续往下走。
而每个执行环境又有它自己的变量对象,里面保存着其中定义的变量和函数。
比如以上代码:在执行var f = fun();之前,当前的执行环境时window,他自己的变量对象是nameStr ,fun等。而fun()的执行环境就是它内部的变量。
当代码在一个环境中执行时,会形成一个变量对象的作用域链,当前环境的变量对象在最前端,其外部函数执行环境的变量对象在下一级,一直回溯到全局环境的变量对象。作用域链是保证了对执行环境有权访问的所有变量和函数的有序访问。当访问一个变量的时候,会从作用域链的最前端开始搜索,逐级向上。
闭包
闭包的概念在各种文献上定义确实比较难懂,这里我在大牛阮一峰的博客里看到最简单的最易懂的解释:闭包就是能够读取其他函数内部变量的函数。
var nameStr = "I am window";
function fun(){
var nameStr = "I am fun";
var f1 = function(){
console.log(nameStr);
}
return f1;
}
var f = fun();
f(); // "I am fun"
上面的代码中f1就是传说中的闭包。
闭包的作用:
一个是可以读取函数内部的变量;
另一个就是让这些变量的值始终保持在内存中。
基于闭包的作用同时也有需要注意的地方:
不能滥用闭包。