欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

5.Javascript闭包得实现原理和作用

程序员文章站 2024-01-29 15:43:16
闭包的实现原理和作用 1、闭包的概念:指有权访问另一个函数作用域中的变量的函数,一般情况就是在一个函数中包含另一个函数。 2、闭包的作用:访问函数内部变量、保持函数在环境中一直存在,不会被垃圾回收机制处理 因为函数内部声明 的变量是局部的,只能在函数内部访问到,但是函数外部的变量是对函数内部可见的, ......

闭包的实现原理和作用

1、闭包的概念:指有权访问另一个函数作用域中的变量的函数,一般情况就是在一个函数中包含另一个函数。

2、闭包的作用:访问函数内部变量、保持函数在环境中一直存在,不会被垃圾回收机制处理

      因为函数内部声明 的变量是局部的,只能在函数内部访问到,但是函数外部的变量是对函数内部可见的,这就是作用域链的特点了。

 子级可以向父级查找变量,逐级查找,找到为止

 1 function  bar(){
 2         //外层函数声明的变量
 3         var value=1;
 4 
 5         function foo(){
 6             console.log(value);
 7         }
 8         return foo();
 9     };
10     var bar2=bar;
11     //实际上bar()函数并没有因为执行完就被垃圾回收机制处理掉
12     //这就是闭包的作用,调用bar()函数,就会执行里面的foo函数,foo这时就会访问到外层的变量
13     bar2();

 

因此我们可以在函数内部再创建一个函数,这样对内部的函数来说,外层函数的变量都是可见的,然后我们就可以访问到他的变量了。

3、闭包的优点:

  • 方便调用上下文中声明的局部变量
  • 逻辑紧密,可以在一个函数中再创建个函数,避免了传参的问题

4、闭包的缺点:

      因为使用闭包,可以使函数在执行完后不被销毁,保留在内存中,如果大量使用闭包就会造成内存泄露,内存消耗很大

 

实际开发中js闭包的应用

1。在函数外使用函数内的变量 .函数作为返回值   (闭包作用:避免变量被环境污染)

1 function f1(){
2   var a = 100;
3     return function(){
4       console.log(a)    
5     }
6 }
7 var f1 =f1();
8 var a = 200;
9 f1()//100

1 function init(){
2     var name = "hello world";//name是一个被init创建的局部变量
3     function sayname(){//sayname是一个内部函数,闭包
4         alert(name);//使用了父级函数声明的变量name
5     }
6     sayname();
7 }
8 init();//"hello world"

 

2.函数作为参数传递

 1 function f1(){
 2    var a = 100;
 3     return function(){
 4       console.log(a)    
 5     }
 6 }
 7 var f1 =f1();
 8 function f2(fn){
 9   var a = 200;
10      fn();
11 }
12 f2(f1);  // 100

 

3.将函数与其所操作的某些数据关联起来,通常,你使用只有一个方法的对象的地方,都可以使用闭包

1 // 改变dom样式
2 document.getelementbyid("a").onclick = setsize(12);
3     document.getelementbyid("b").onclick = setsize(18);
4     document.getelementbyid("c").onclick = setsize(22);
5     function setsize(fontsize){
6         return function(){
7             document.body.style.fontsize = fontsize + 'px';
8         }
9     }

 

4.用闭包模拟私有方法

 1 //这三个公共函数是共享同一个环境的闭包。多亏 javascript 的词法作用域,它们都可以访问 privatecounter 变量和 changeby 函数。
 2 var makecounter = function () {
 3         var privatecounter = 0;
 4         function changeby(val){
 5             privatecounter += val;
 6         };
 7         return {
 8             increment: function(){
 9                 changeby(1);
10             },
11             decrement: function(){
12                 changeby(-1);
13             },
14             value: function(){
15                 return privatecounter;
16             }
17         }
18     };
19     var counter1 = makecounter();
20     var counter2 = makecounter();
21     counter1.increment();
22     console.log(counter1.value());//1 每次调用其中一个计数器时,通过改变这个变量的值,会改变这个闭包的词法环境。然而在一个闭包内对变量的修改,不会影响到另外一个闭包中的变量。
23     console.log(counter2.value());//0 以这种方式使用闭包,提供了许多与面向对象编程相关的好处 —— 特别是数据隐藏和封装。

 

5.循环里面的闭包

怎么才能实现输出0-5呢?

1 for (var i = 0; i < 5; i++) {
2   settimeout(function () {
3     console.log(i);
4   }, 1000 * i);
5 }//55555
//方法一,makecallback函数为每一个回调创建一个新的词法环境。
function makecallback(i) {
     return function() {
        console.log(i)
      };
    }
    for(var i=0;i<10;i++){
        settimeout(makecallback(i),1000)
    }
//另一种方法使用了匿名闭包
for(var i=0;i<10;i++){
        (function(i){
            settimeout(function () {
                console.log(i)
            },1000)
        })(i)
    }
1 //使用let声明变量
2 for (let i = 0; i < 5; i++) {
3   settimeout(function () {
4     console.log(i);
5   }, 1000 * i);
6 }