关于闭包的一点探索

 看前两章即可

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

 

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

 

posted @ 2018-09-25 16:07  朋友圈  阅读(133)  评论(0编辑  收藏  举报