JavaScript 自执行函数(闭包)

3/8/2017来源:ASP.NET技巧人气:2237

1. 全局污染

在变量声明的时候有一个规则:重复声明无效 var num = 123; var num = 'abc'; 重复声明的代码不会报任何错误,但是其声明特征就没有了,会转换成普通赋值语句 故,上述代码与下面代码等价 var num = 123; num = 'abc'; 例:
<script src="jquery.js"></script>
<script>
    var $ = function(selector){
        return document.querySelectorAll(selector);//给$重新赋值了
    };
    $('div').CSS(...);//报错,此时$('div')是nodeList类型,没有css方法
</script>







2. 闭包

起因:在函数内部声明的数据,在函数外是不能够直接访问的。 闭包含义:就是包裹、包装的意思。闭表示封闭,即不可访问。     所谓的闭包就是一个具有封闭的特性,同时具有包裹的特性的一种结构。     从代码的角度说,所谓的闭包就是函数。 ① 函数内声明的变量,外界无法访问,即封闭性。 ② 函数本身又是一个封装单位,利用函数可以封装代码,因此一个函数也是一个包裹结构。 因此函数既有包裹的特性,也有封闭的特性,因此可以直接称呼函数为闭包 (closure) 凡是函数要执行,就会分配内存空间以供函数执行 如果函数执行结束,内存会被释放,即可以重复使用 这个定义是有缺陷的。 如果函数内部将数据的引用返回到外部,那么就可以保证数据被一直占用。
function foo(){
    var num = 123;
    function func(){
        return num;
    }
    return func;
}
var f = foo(); 
// f指向func,foo不可以被释放,因为func
// num不能被释放,因为f会返回该数据










3. 所谓的闭包就是函数,其特点是函数内定义的变量,在函数外是无法访问的。

但是闭包需要解决的问题是如何间接的访问到这些数据。 如何访问函数中的数据? ① 最简单的访问方式:返回
function foo(){
var num = 123;
return num;
}
var res1 = foo();
var res2 = foo();
//但两次访问的并不是同一个数据


② 多次访问,f 只允许调用一次
var res1 = foo();
var res2 = res1;



③ 使得函数返回一个函数,利用函数返回数据
function f(){
var num = 123;
return function(){
        //作用域访问规则,是可以访问num的
    return num;
    };
}
var foo = f();//先执行,只调用了一次
var res1 = foo();//获取num的值
var res2 = foo();//访问的是同一个值


将2级链返回到0级链中,利用2级链可以访问1级链的特性,使得0级链间接的访问到1级链。





因此这个数据是不能被销毁的,即不能被释放。




小结:

所谓的闭包,就是一个函数,因为函数中声明的变量,外界无法访问,函数就构成了封闭结构,因此成为闭包。

同时如果需要访问函数中的数据,可以考虑利用函数返回一个函数,使用返回的函数操作函数内的数据,以使得函数外可以通过这个函数内返回的函数,访问内部的数据。











4. 补充:内存释放

在 js 中凡是不被使用的数据,可以被释放






5. 闭包的用法

(1)作为沙箱模式

沙箱:就是一个独立的与外界隔离的运行环境(function)
(function(){
    //此处的代码,对外隔离,外界无法访问,但是可以执行
})();


暴露方式:
var foo = (function(){
function foo(){}
    return foo;
})();

(2)带有缓存功能的函数

var func = (function(){
    //私有数据
    return function foo(){
    };
})();
//func带有私有数据



递归中,为什么性能低?

因为重复的太多了,将已经计算好的存储起来,如果没有计算,就递归,但是算完以后还是存起来。