js闭包精解!

386 阅读2分钟

闭包是js学习中不能绕过去的一个坑,初学者一般都会问闭包到底有什么用呢,我们直接需要的时候定义一个变量它不香吗,为什么一定要把一个变量困住呢,还占用内存,但其实有很多例子中我们是非要用到闭包不可的。

一.闭包的概念

闭包就是在外部函数内部定义了内部函数,内部函数中引入了外部函数的局部变量,当外部函数执行完毕后,局部变量并不会被释放。将变量留在了内存中,将来可以使用。

二.闭包的重要应用

  • 私有变量的实现

我们都知道在c中都是可以在构造函数内部构造私有变量的,但是在js中你会怎么办呢?有请闭包小姐:

//私有变量实现
function Person(_name,_age) {
    this.name=_name;
    let age =_age;
    this.setAge=function() {
        this.age = age;
    }
    this.getAge=function() {
        return this.age;
    }
}
let per = new Person('xpp',26);
per.setAge();
console.log(per.getAge())

  • DOM文档获取元素索引(解决ES5中没有块级作用域问题)

    先看没有使用闭包时的代码:

<body>
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
</ul>
<script>
    window.onload=function () {
        let ul = document.querySelectorAll('li')
        for(var i=0;i<3;i++){
            ul[i].onclick = function () {
                alert(i);
            }
        }
    }
</script>
</body>
会发现不管你点击哪一个元素弹出来的都是3.这是因为在ES6之前并没有块级作用域,i是一个全局变量,当页面加载完成时for循环已经执行完了,所以不管点击哪个结果都是3,下面我们看使用了闭包后的代码:

<body>
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
</ul>
<script>
    window.onload=function () {
        let ul = document.querySelectorAll('li')
        for(var i=0;i<3;i++){
            (function set(j){
                ul[j].onclick = function () {
                    alert(j);
                }
            })(i)
        }
    }
</script>
</body>
就可以正常获得DOM元素的索引值了,因为闭包的存在,所以函数的局部变量不能被释放

  • 闭包实现计时器传参效果

function fn(data) {
    return function () {
        console.log(data)
    }
}
let f1=fn('xpp');
setTimeout(f1,100)

  • 闭包实现模块化统计用于点击量功能

function Tracker() {
    var accessCounter = 0;
    var accessAd = [];
    return {
        accessAdd:function (page) {
            accessAd.push(page)
        },
        getAccessAd:function () {
            return accessAd;
        },
        addAccessCounter:function () {
            accessCounter++;
        },
        getAccessCounter:function () {
            return accessCounter;
        }
    }
}
let track = Tracker();
track.addAccessCounter();
console.log(track.getAccessCounter())