js基础-作用域和作用域链以及闭包
作用域概念:
作用域:变量可访问的范围。
在 JavaScript 中, 对象和函数同样也是变量。
在 JavaScript 中, 作用域为可访问变量,对象,函数的集合。
JavaScript 函数作用域: 作用域在函数内修改。
作用域分类:
全局作用域 和局部作用域
局部作用域:
变量在函数内声明,只能在函数内部访问,即局部变量
函数参数也是局部变量
因为局部变量只作用于函数内,所以不同的函数可以使用相同名称的变量。
全局作用域:
变量在函数外定义,即为全局变量
全局变量有 全局作用域: 网页中所有脚本和函数均可使用。
如果变量在函数内没有声明(没有使用 var 关键字),该变量为全局变量。
在 HTML 中, 全局变量是 window 对象: 所有数据变量都属于 window 对象。
1 var a = 100;//全局 2 function fn(){ 3 var a =200; 4 console.log('函数作用域',a); 5 } 6 console.log('全局作用域',a); //全局作用域 100 7 fn();//函数作用域 200
JavaScript 变量生命周期:
JavaScript 变量生命周期在它声明时初始化。
局部变量在函数执行完毕后销毁。
全局变量在页面关闭后销毁。
js中无块级作用域
1 if(true){ 2 var name = 'tml'; 3 } 4 console.log(name); //tml 因为无块级作用域,不会报错
无块级作用域可能带来的影响
1)变量提示导致内部变量可能覆盖外层变量
var i = 5; function func(){ console.log(i); if(true){ var i = 6; } } func();//undefined
2)局部变量可能泄露为全局变量
1 for(var i = 0; i < 10; i++){ 2 console.log(i); 3 } 4 console.log('i',i);//10
可通过let ,const 或闭包解决这些影响
作用域链
概念:当声明一个函数时,局部作用域一级一级向上包起来,就是作用域链
1.函数中,变量先从局部作用域找,未找到,则去上一层局部作用域找,没有,则去全局作用域找,全局未找到,则报错;
2.当前作用域没有定义的变量,即为‘自由变量’
var a = 100; function fn(){ var b =201; console.log('a',a);//a 自由变量 console.log('b',b); console.log('c',c); } fn();
结果:
提到作用域,就很容易想到闭包。
闭包是什么?
保护并重用局部变量的词法结构
何时使用闭包?
共享局部变量,且不希望被随便篡改时
构建闭包3步骤:
1.使用外层函数封装受保护的局部变量 和 专门操作变量的内层函数
2.外层函数将内层函数返回(return)到外部
3.在全局调用外层函数,获得内部函数的对象,保存在全局变量中反复使用
根据闭包特点判断闭包:
1. 嵌套函数
2. 内层函数使用了外层函数的局部变量
3. 内层函数对象被返回到外部,在全局反复调用
优点:闭包可以形成独立的空间,永久的保存局部变量。
缺点:1)保存中间值的状态缺点是容易造成内存泄漏,因为闭包中的局部变量永远不会被回收
2)闭包占内存过高
1 function F1(){ 2 var a =100; 3 4 return function (){//返回一个函数(函数作为返回值) 5 console.log(a); 6 } 7 } 8 var f1 = F1();//f1得到一个函数 9 var a =200000; 10 f1();//100
1 function addCount() { 2 var num= 0; 3 return function() { 4 num= num+ 1; 5 console.log(num); 6 }; 7 } 8 var aa = addCount();//外层函数返回内层函数 9 aa();//1
结果: