江西哪里有卖当归种子的?

小说:江西哪里有卖当归种子的?作者:侯扁北更新时间:2019-05-27字数:71372

什么是闭包

一个函数a定义在另一个函数b里面,这个函数a就是闭包

function b() {
    ...
    function a() { //闭包
        ...
    }
    ...
}

同时,函数a能够直接读取函数b的变量,这个就是闭包的特性

function b() {
    var x = 1;
    function a() {
        alert(x);
    }
    a();
}
b(); //1

再来看个更有意思的例子:

function b() {
    var x = 1;
    function a() {
        alert(x++);
    }
    return a;
}
var func = b();
func(); //1
func(); //2
func(); //3

函数b这次不直接执行a,而是返回了a,所以func是函数a实例的引用,而func()竟然能神奇地记住x,这得益于JavaScript的闭包机制。

综上所述,结合以上代码来看,闭包就是函数a和变量x,也就是书上说的:

函数以及它所连接的周围作用域中的变量即为闭包

闭包:使得函数可以维持其创建时所在的作用域。如果一个函数离开了它被创建时的作用域,它还是会与这个作用域以及其外部的作用域的变量相关联。

为什么要用闭包

我们其实经常用到闭包,可能自己都不知道,比如下面这个例子,一个初始化函数里面包含一个按钮点击事件:

function init(){
    ...
    document.getElementById("btn").onclick = function(){ //闭包
        ...
    };
}

一个详细点的例子,比如发送验证码

<!DOCTYPE html>
<html lang="zh-cn">
<head></head>
<body>
<button type="button" id="getCode">获取验证码</button>

<script>
init();

function init(){
    var time_wait = 60; //等待时间
    var time_left = time_wait; //剩余等待时间
    document.getElementById("getCode").onclick = function(){ //闭包
        var btn = this;
        btn.disabled = true;
        btn.innerHTML=time_left--;
        var count = setInterval(function(){ //闭包
            if(time_left<1){
                btn.disabled = false;
                btn.innerHTML="获取验证码";
                time_left = time_wait;
                clearInterval(count);
            }else{
                btn.innerHTML=time_left--;
            }
        },1000);
    };
}
</script>
</body>
</html>

可以看到在onclick函数里面是可以正常操作time_wait和time_left变量的,细心的朋友可能已经发现这里出现两个闭包了,一个是onclick,还有一个是setInterval定时函数。

所以回过头来看问题,为什么要用闭包?

  • JavaScript语言特性需要(setTimeout、setInterval...)
  • 事件绑定需要(onclick...)

当然还有一个更重要的原因需要它,那就是OO,把上面发送验证码的代码改造一下变成面向对象风格

var c = new CountDown(document.getElementById("getCode"), 5);
c.run();

function CountDown(btn, time_wait) {
    var time_left = time_wait; //剩余等待时间
    
    //private
    function resetBtn(){
        btn.disabled = false;
        btn.innerHTML="获取验证码";
    }
    
    //public
    this.run = function(){
        btn.onclick = function(){
            btn.innerHTML=time_left--;
            btn.disabled = true;
            var count = setInterval(function(){
                
                if(time_left<1){
                    resetBtn();
                    time_left = time_wait;
                    clearInterval(count);
                }else{
                    btn.innerHTML=time_left--;
                }
            },1000);
        };
    };
}

什么时候不要用闭包

滥用闭包可能会导致脚本执行缓慢并消耗不必要的内存

1.循环

<!DOCTYPE html>
<html lang="zh-cn">
<head></head>
<body>
    <input type="button" id="btn1" value="1" />
    <input type="button" id="btn2" value="2" />
    <input type="button" id="btn3" value="3" />

    <script>
    window.addEventListener("load", function() {
        for (var i = 1; i < 4; i++) {
            var btn = document.getElementById("btn" + i);

            btn.addEventListener("click", function() {
                alert(i);
            });
        }
    });
    </script>
</body>
</html>

无论你点击哪个按钮,都会弹出4,因为click函数是个闭包,页面加载后循环开始执行,当你点击按钮的时候,循环已经执行完了,此时i值为4,而闭包记得它周围的变量,所以弹出的都是4。
要解决这个问题,可以把打印的代码提炼到另一个函数里面,这样就会产生一个新的作用域:

function show(i){
    return function(){
        alert(i);
    }
}

window.addEventListener("load", function() {
    for (var i = 1; i < 4; i++) {
        var btn = document.getElementById("btn" + i);

        btn.addEventListener("click", show(i));
    }
});

或者用立即执行函数表达式:

window.addEventListener("load", function() {
    for (var i = 1; i < 4; i++) {
        var btn = document.getElementById("btn" + i);

        btn.addEventListener("click", function(i) {
            return function(){
                alert(i);
            }
        }(i));
    }
});

2.构造器

方法应该关联于对象的原型,而不要定义到对象的构造器中。原因是这将导致每次对象实例化时,方法都会被重新定义一次。

function User(name) {
    this.name = name;

    this.getName = function() {
        return this.name;
    };
}

改成如下,继承的原型可以为所有实例共享:

function User(name) {
    this.name = name;
}

User.prototype.getName = function() {
    return this.name;
};

参考资料

  1. 阮一峰>学习Javascript闭包
  2. MDN>Web技术文档>JavaScript>闭包
  3. JavaScript Closures Demystified
  4. JavaScript for PHP Developers
  5. 深入理解JavaScript

当前文章:http://www.cnsdbtzg.com/news-173753

发布时间:2019-05-27 02:54:22

棣棠最佳的种植密度是多少棵? 河南红叶小檗多少钱一棵? 4.5公分金镶玉竹什么价格? 贵州贴梗海棠球价格高吗? 15公分银杏树价格 金丝柳成活率高吗? 广西可以栽植红花继木吗? 护坡用什么草籽最好? 高丹草种子价格是多少? 二月兰种子几月播种最好?

48457 64525 39846 98739 26833 38127 40016 42405 64194 15067 89512 13886 68926 15854 35985 10417 39913 37203 86431 86366 79473 15633 93493

我要说两句: (0人参与)

发布