博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于闭包的一点探索
阅读量:5809 次
发布时间:2019-06-18

本文共 3505 字,大约阅读时间需要 11 分钟。

 看前两章即可

https://www.cnblogs.com/xiangqianjin/p/6595115.html

 

一、闭包用来访问内部变量

但是对于对象来说,直接return this.xxx也可以访问

var name = 'The Window';var obj = {  name:'My Object',  getName:function(){    return this.name;  }}console.log(obj.getName());

 

如果直接return name,没用this的话,返回的是全局的

var name = 'The Window';var obj = {  name:'My Object',  getName:function(){    return name;  }}console.log(obj.getName());

因为此时,这个name根本没和上下文关联,函数直接去找全局的name了

 

如果返回的是一个函数呢?

这个就是那篇博客中的例子

var name = 'The Window';var obj = {  name:'My Object',  getName:function(){    return function(){      return this.name;    }  }}console.log(obj.getName()());

首先调用getName返回了一个函数,这个函数是

function(){      return this.name;    }

 

我们相当于在全局环境调用了这个函数,所以是全局的name

这个没什么好纠结的。

所以对象成员的话,和闭包没啥关系,因为通过obj.name 和 return this.name 都能访问

如果想给对象增加私有变量,才会用到闭包,且不能通过成员变量来声明。

比如说,年龄age

var obj = {  var age = 10;  name:'My Object',  }

外部是访问不到的

 

好吧,类是不能这样声明变量的

 

 可以通过构造函数去实现。

function Student(age,name){  //私有变量  var age = age;  //公有变量  this.name = name;  //公有函数  this.getName = function(){    return this.name;  }}var xiaoming = new Student(10,'xiaoming');console.log(xiaoming.getName());

 

那小明的age怎么访问呢?

这样行不行?

this.getAge = function(){    return age;  }

可以!强吧?

但是,this就不行,因为上面已经表示,类里面没有age这个变量

this.getAge = function(){    return this.age;  }

 

但是如果,全局里又有一个age呢?

var name = 'The Window';function Student(age,name){  //私有变量  var age = age;  this.getAge = function(){    return age;  }  //公有变量  this.name = name;  //公有函数  this.getName = function(){    return this.name;  }}var age = 20;var xiaoming = new Student(10,'xiaoming');console.log(xiaoming.getName());

还是10,那闭包不是多此一举????

var xiaoming = new Student(10,'xiaoming');var xiaohong = new Student(40,'xiaoming');

还互不影响呢!!! 闭包的意义是啥?

 

 

可以通过闭包去访问

function Student(age,name){  //私有变量  var age = age;  //访问age  this.getAge = function(){    return function(){      return age;    }  }  //公有变量  this.name = name;  //公有函数  this.getName = function(){    return this.name;  }}

其实和复杂的写法一样

总之就是要返回一个,可以访问到内部变量age的函数,这个函数在哪定义都行

function Student(age,name){  //私有变量  var age = age;  //访问age  function a(){    return age;  }  this.getAge = function(){    return a;  }  //公有变量  this.name = name;  //公有函数  this.getName = function(){    return this.name;  }}

 

创建一个setter也可以直接创建

 

function Student(age,name){  //私有变量  var age = age;  this.getAge = function(){    return age;  }  this.setAge = function(newAge){    age = newAge;  }  //公有变量  this.name = name;  //公有函数  this.getName = function(){    return this.name;  }}var age = 20;var xiaoming = new Student(10,'xiaoming');

 

 

私有变量、setter、getter这么容易,要闭包干嘛呢?

https://www.cnblogs.com/zxjwlh/p/4420590.html

 

二、函数里面使用闭包

就是为了访问内部变量,因为函数没有对象那么好用

function f1(){  var n = 999;  function f2(){    return n;  }  return f2;}

 

应用场景有什么呢?

 

先了解一个用法,给回调函数显式传参并调用

for(let i=0;i<4;i++){  //当前的i  // console.log(i);  //执行的回调函数,顺便在执行的时候给他传参  setTimeout(function(a) {    //全局的i    console.log(a);  }(1),1000);}

回调的形参是a,实参是1

最后打印4个1

 

 

for(var i=0;i<4;i++){  setTimeout(function() {    console.log(i);  },1000);}

这个函数的执行

因为setTimeout的执行逻辑,它是异步事件,所以会在同步事件执行完之后再执行,同步事件执行完之后,就是跳出循环,i已经是4了。

 

 这样输出正常了。。

为什么啊?我也不明白

for(var i=0;i<4;i++){  setTimeout(function(i) {    console.log(i);  }(i),1000);}

 

 

用let可以完美解决,因为let是局部变量

for(let i=0;i<4;i++){  setTimeout(function() {    console.log(i);  },1000);}

 

解决方法可以参考这篇文章

https://www.jb51.net/article/122489.htm

很好理解,但是文章里面说setTimeout不支持带参数的函数,但是我这边的可以的???

 

 

垃圾回收机制

https://blog.csdn.net/yingzizizizizizzz/article/details/77333996

 

但是还有一点没有说明白,为什么闭包,不会被回收?

 

转载于:https://www.cnblogs.com/weizhibin1996/p/9700038.html

你可能感兴趣的文章
微服务架构会和分布式单体架构高度重合吗
查看>>
如何测试ASP.NET Core Web API
查看>>
《The Age of Surge》作者访谈
查看>>
测试人员的GitHub
查看>>
Spring Web Services 3.0.4.RELEASE和2.4.3.RELEASE发布
查看>>
有关GitHub仓库分支的几个问题
查看>>
无服务器计算的黑暗面:程序移植没那么容易
查看>>
云原生的浪潮下,为什么运维人员适合学习Go语言?
查看>>
Webpack入门教程三十
查看>>
EAServer 6.1 .NET Client Support
查看>>
锐捷交换机密码恢复(1)
查看>>
Kali linux virtualbox rc=1908 错误解决办法
查看>>
Erlang学习总结之Erlang语法中的逗号(,)、分号(;),句号(.)的正确用法...
查看>>
linux软件包管理之三(源代码安装)
查看>>
数据库三范式是什么?
查看>>
[转载]设置Ubuntu自动连接无线,无须再输入密钥环和无线密码
查看>>
九叔Xen App测试报告
查看>>
Apache配置
查看>>
Ext gridPanel 单元格数据的渲染
查看>>
Android SDK 的下载代理
查看>>