js之闭包(概念、优缺点、应用)

4.2 闭包

4.2.1 闭包的定义

闭包是指有权访问另一个函数作用域中变量的函数。创建闭包的最常见的方式就是在一个函数A内创建另一个函数B,通过函数B访问函数A局部变量。(js高级教程)

4.2.2 闭包优缺点

1 闭包的作用(优点)

1)读取另一个函数作用域中的变量;

2)让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在。

3封装对象的私有属性和私有方法。(然后在全局作用域中通过调用闭包就能访问函数中的变量)

2 闭包的缺点(坏处)

由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存,过度使用闭包可能会导致内存占用过多的问题。

所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

4.2.3 闭包的应用

闭包的应用—循环中使用闭包解决 var 定义函数的问题

/*变量i是var命令声明的,在全局范围内都有效,所以全局只有一个变量i。

  每一次循环,变量i的值都会发生改变,而循环内setTimeout的回调函数中使用console.log(i),

  里面的i指向的就是全局的i。

*/

 

  for( var i=1; i<=5; i++) {

    setTimeout( function timer() {

        console.log( i );

    }, i*1000);

}  //输出5个6

//因为 setTimeout 是个异步函数,所有会先把循环全部执行完毕,这时候 i 就是 6 了,所以会输出一堆 6。

解决方法

1)使用闭

for (var i = 1; i <= 5; i++) {
    (function(j) {
        setTimeout(function timer() {
            console.log(j);
        }, j * 1000);
    })(i);
} //1 2 3 4 5(每行一个数字)

2)使用 setTimeout 的第三个参数

for ( var i=1; i<=5; i++) {
    setTimeout( function timer(j) {
        console.log( j );
    }, i*1000, i);
}

3)使用let

for ( let i=1; i<=5; i++) {

    setTimeout( function timer() {

        console.log( i );

    }, i*1000 );

}

4.2.4 闭包的注意点:闭包中的this以及arguments对象(js高级程序设计)

this对象是在运行时基于函数的执行环境绑定的。

每一个函数在调用时都会自动取得两个特殊的变量:this和arguments。内部函数在搜索这两个变量时,只会搜索到其活动对象为止,因此永远不可能直接访问外部函数中的这两个变量。不过,如果把外部作用域中的this和arguments对象保存在一个闭包能够访问的变量里面,就可以在闭包中访问者两个对象了。其应用可以看防抖节流、apply等手写实现。

在下面的例子中对象obj中方法getName定义了一个闭包。使用obj.getName(18)调用闭包的外部函数,其getName中的thisarguments指向obj [Arguments] { '0': 18 }。在全局中调用闭包,在非严格模式下的浏览器中,其this指向全局对象window

var name = "outer";
var obj = {
    name: "inner",
    getName: function (age) {   //闭包
        console.log(this, arguments);  //  { name: 'inner', getName: [Function: getName] } [Arguments] { '0': 18 }
        return function () {
             return {
                 th: this,
                 age: age,
                 na: name,
                 arg: arguments
             }
        }
    }
}
var func = obj.getName(18);   //获得闭包, getName中的this和arguments指向obj和 [Arguments] { '0': 18 }
var result = func(12, "多余的参数");    //执行闭包  闭包中的this和arguments指向undefined(浏览器为window)和 [Arguments] { '0': 12, '1': '多余的参数' } }
console.log(result);
/*console.log(obj.getName(18)(12, "多余的参数"));*/    //这句和上面三句执行结果一样

/*node环境下的返回值
{ th:Object [global] {...}     //注意这里,谷歌浏览器返回的是window对象
  age: 18,
  na: undefined,     //谷歌浏览器是outer
  arg: [Arguments] { '0': 12, '1': '多余的参数' } }*/

1)node环境下返回值截图(上)

 

中间一堆node全局环境。。

 

2)浏览器返回值截图

 

js之闭包(概念、优缺点、应用)_第1张图片

 

4.2.5 相关面试题目

1 循环中使用闭包解决 var 定义函数的问题(答案:其应用里面就是)

2

4.2.6 总结js之闭包(概念、优缺点、应用)_第2张图片

 

百里于2020年7月20日

如果有错,请您指出!如有侵权,请联系我删除!

你可能感兴趣的:(#,js专题,js,闭包)