一、变量作用域
变量的作用域有两种:全局变量和局部变量,而js有特殊的作用域,即:函数内部可直接访问全局变量,而函数外面没法访问函数内的局部变量.
JS代码
var n = 99; function f1(){ console.log(n); } f1();//99 function f2(){ var m = 999;//注意点:当在函数内部声明变量时,必须用var命令,否则就会被浏览器认为是全局变量 } console.log(m);//thorw error
二、如何从外部获取局部变量
正常情况下是访问不到的,但是我们解决方法,就是在函数的内部再定义一个函数,把内部函数的作为返回值,就可以解决了。如下:
function f1(){ var n = 88; function f2(){ return n; } return f2; } var result = f1(); result();//88 //此时,result就是f2这个函数,故需要加() result;// function f2(){return n;}
在上面代码中,f2包含在f1内,则f2可访问f1内部的所有变量,反之,不行!即父对象的所有变量对子对象都是可见的.这就是javascript的“链式作用域”
三、闭包的概念
简单来说,上面f2就是闭包函数了,就是能够读取其他函数内部变量的函数。可定义为,在一个函数内部定义的函数,或者说当函数a的内部函数b被a外的一个变量引用时,就创建了闭包。本质上来说,闭包就是将函数内部和外部连接起来的一座桥梁。
四、闭包的用途
有人说,javascript闭包是走向js高级程序员的必经之路,我觉得是很合理的。首先它有两大用途:一方面,可以获取函数内部的变量;另一方面,让这些函数内部变量始终保存在内存中,可随时调用。下面上栗子
function f1(){ var n = 77; add = function(){//add为全局的匿名函数 n++; } function f2(){ return n; } return f2; } var result = f1(); result();//77 add(); result();//78 //说明f1的内部变量一直保存着,而没有被清除
五、使用闭包的注意点
- 闭包函数中变量都被保存,内存消耗较大,不能滥用,在IE中会导致内存泄漏,解决方法是在函数退出之前,把不适用的内部变量全部清除;
- 闭包会在函数外部改变函数内部边变量的值,此时父函数当作对象,闭包为公用方法,内部变量为私有属性,则不可随便修改父函数内部变量的值;
六、闭包的应用场景
- 由于函数内部变量不能被外部访问,敢保证了变量的安全性;
- 在内存中维持一个变量,由于闭包作用,一直存在于内存中,每次回调执行都会获取到上一步的值;
- 通过保护内部变量,实现了js的私有属性和私有方法;
七、Javascript的垃圾回收机制
额外增加的一点,就是垃圾回收机制,在Javascropt中,如果一个对象不再被引用,则这个对象就会被回收;如果两个对象互相引用,而不被第三个对象引用,也会被回收。js有两种垃圾回收机制,一种是标记清除,一种是引用计数
- 标记清除:变量进入某个环境时会被标记,离开时标记离开,这种常用
- 引用计数:跟踪每个值被引用的次数,当声明一个变量并将一个引用类型的值赋给该变量时,这时该变量的引用计数值+1;相反,如果包含这个值得引用的变量又取得另外一个值,即被重新赋值,那么就-1;当这个值为0时,就回收该变量占用的内存空间
就说这么多,以后会专门写一篇内存回收的,这里只是提及一下。