zoukankan      html  css  js  c++  java
  • 还是JQuery闭包!

    如果在一个外部函数中再定义一个内部函数,即函数嵌套函数,那么内部函数也可以访问外部函数中的变量:

    function foo(x) {
    	var tmp = 3;
    	function bar(y) {
    		alert(x + y + (++tmp));
    	}
    	bar(10);
    }
    
    foo(2); // alert 16
    foo(2); // alert 16
    foo(2); // alert 16

    此段代码可以正确执行,并返回结果:16,因为 bar 能访问外部函数的变量 tmp, 同时也能访问外部函数 foo 的参数 x。但以上示例不是闭包

    要实现闭包的话,需要将内部函数作为外部函数的返回值返回,内部函数在返回前,会将所有已访问过的外部函数中的变量在内存中锁定,也就是说,这些变量将常驻 bar 的内存中,不会被垃圾回收器回收,如下:

    function foo(x) {
    	var tmp = 3;
    	return function (y) {
    		alert(x + y + (++tmp));
    	}
    }
    var bar = foo(2); // bar 现在是个闭包了
    bar(10); // alert 16
    bar(10); // alert 17
    bar(10); // alert 18

    上述代码中,第一次执行 bar 时,仍会返回结果:16,因为 bar 仍然可以访问 x 及 tmp,尽管它已经不直接存在于 foo 的作用域内。那么既然 tmp 被锁定在 bar 的闭包里,那么每次执行 bar 的时候,tmp 都会自增一次,所以第二次和第三次执行 bar 时,分别返回 17 和 18。

    此示例中,x 仅仅是个纯粹的数值,当 foo 被调用时,数值 x 就会作为参数被拷贝至 foo 内。

    但是 JavaScript 处理对象的时候,使用的总是引用,如果用一个对象作为参数来调用 foo,那么 foo 中传入的实际上是原始对象的引用,所以这个原始对象也相当于闭包了,如下:

    function foo(x) {
    	var tmp = 3;
    	return function (y) {
    		alert(x + y + tmp++);
    		x.memb = x.memb ? x.memb + 1 : 1;
    		alert(x.memb);
    	}
    }
    var age = new Number(2);
    var bar = foo(age); // bar 现在是个闭包了
    bar(10); // alert 15 1
    bar(10); // alert 16 2
    bar(10); // alert 17 3
    和期望的一样,每次执行 bar(10) 时,不但 tmp 自增了,x.memb 也自增了,因为函数体内的 x 和函数体外的 age 引用的是同一个对象。


    补充:通过以上示例,应该能比较清楚的理解闭包了。如果觉得自己理解了,可以试着猜猜下面这段代码的执行结果:

    function foo(x) {
    	var tmp = 3;
    	return function (y) {
    		alert(x + y + tmp++);
    		x.memb = x.memb ? x.memb + 1 : 1;
    		alert(x.memb);
    	}
    }
    var age = new Number(2);
    var bar1 = foo(age); // bar1 现在是个闭包了
    bar1(10); // alert 15 1
    bar1(10); // alert 16 2
    bar1(10); // alert 17 3
    
    var bar2 = foo(age); // bar2 现在也是个闭包了
    bar2(10); // alert ? ?
    bar2(10); // alert ? ?
    bar2(10); // alert ? ?
    
    bar1(10); // alert ? ?
    bar1(10); // alert ? ?
    bar1(10); // alert ? ?

    试着猜猜代码注释中 ? 的值。

  • 相关阅读:
    通过电脑chrome调试手机真机打开的微信H5页面,调试电脑微信H5页面
    关于神策埋点数据采集
    jmeter控制仅一次登录的三种方案
    win10下mysql8.0.19解压版的安装教程
    mysql中的case when then 的用法
    python+openpyxl的excel的相关读写
    使用Gitlab-CI 实现NetCore项目Docker化并部署到阿里云K8S
    NetCore 中间件获取请求报文和返回报文
    WebApi 通过拦截器设置特定的返回格式
    NetCore AutoMapper的封装
  • 原文地址:https://www.cnblogs.com/yangzhi/p/3576565.html
Copyright © 2011-2022 走看看