zoukankan      html  css  js  c++  java
  • 闭包是什么?

    原文链接:http://www.qdfuns.com/notes/17398/9b28ba7e036240b1252f1c82b9883d94.html

    老姚说:

    产生闭包的三个条件:

    1. 调用的函数是父级作用域内部声明的
    2. 调用的函数是在父级作用域之外进行调用
    3. 调用的函数内部使用了父级作用域的内部变量

    闭包举例

    1.作为函数返回结构的一部分

    var fun = function() {
            var x = 0;
            return {
                    fn: function() {
                            alert(++x);
                    } 
            };
            }
    var r = fun();
    r.fn();
    r.fn();
    

    r.fn是fun的内部函数(注意函数是引用类型的),调用是在fun的外部调用的。

    2.赋给外部变量

    var fun1;
    var fun2 = function() {
            var x = 0;
            fun1 = function() {
                    alert(x);
            }
            }
    fun2();
    fun1();
    

    其中fun1是个闭包,条件都满足。有疑问的地方可能是,是否内部声明的呢?是的,因为fun1是个函数,是fun2的内部函数。

    3.异步操作,绑定到dom事件

    var fun2 = function() {
            var btn = document.querySelector("#myBtn");
            var x;
            btn.onclick = function() {
                    alert(x);
            }
            }
    fun2();
    

    主要看看是否是外部调用。是的。因为用户点击时触发事件,不是在fun2中内部调用的。
    如果btn是外部声明的,跟情况2差不多。

    4.异步操作,setTimeout或setInterval

    var fun = function(x) {
            setInterval(function() {
                    console.log(x++);
            }, 3000)
            }
    fun(1);
    

    setInterval第一个参数,是一个函数,此函数的执行必须是在全局调用的。因此是闭包。

    5.异步操作,ajax请求回调

    6.特权函数

    var Person = function() {
            this.sayName = function() {
                    alert(name);
            }
            var name = "laoyao";
            }
    var p = new Person();
    p.sayName();
    

    上面我故意把sayName和name写反的,没有问题的。
    只要是闭包,使用的外部变量位置“在哪”都可以的。当然闭包不是本质原因,只要在函数调用之前就行了。而闭包是在外部调用的。
    这里来说说它为啥是闭包呢?
    p.sayName是个构造函数内部声明的匿名函数,没问题。
    调用时也是在构造函数之外调用。

    写到这里,回想当初写的第一篇文章说闭包是一个函数的返回值,并引用了函数内部变量。现在看来还是太年轻。让怨念先飞一会儿。
    最后,再来一个更深层的例子。

    var fun1 = function() {
            var x = 1;
            return function fun2() {
                    var y = 5;
                    return function fun3() {
                            alert("x=" + (++x) +";y=" +(++y));
                    }
            }
            }
    var fun2 = fun1();
    var fun3 = fun2();
    fun3();
    fun3();
    

    fun2和fun3都是闭包。如果结合上面的几种情况,类似的例子能写出很多。

  • 相关阅读:
    Vue GET xxxx/sockjs-node/info?t=1573626343344 net::ERR_CONNECTION
    NavigationDuplicated Navigating to current location (“/XXX”) is not allowed
    node-sass报错(Node Sass could not find a binding for your current environment)
    DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead
    VSCODE 中.art文件识别为html文件
    gulp4.0构建任务
    gulp报错The following tasks did not complete
    setTimeout()
    格式化日期
    作业1.3
  • 原文地址:https://www.cnblogs.com/bluey/p/6417775.html
Copyright © 2011-2022 走看看