JavaScript 面试题(二十一)闭包,什么情况下会使用闭包?

闭包定义

一个函数对其周围状态的引用捆绑在一起,这样的组合就是闭包(或者说,函数被引用包围)。闭包可以让你在一个内层函数中可以访问到外层函数的作用域。

function fnOut() {
        var name = '张三'
        function fnIn() {
            alert(name)
        }
        fnIn()
    }
    fnOut()
function fnOut() {
        var name = '李四'
        function fnIn() {
            alert(name)
        }
        return fnIn
    }

    let myFn = fnOut()
    myFn()
 function fn1(x) {
        return function fn2(y) {
            return x + y
        }
    }

    let add2 = fn1(2)
    let add4 = fn1(4)

    console.log(add2(3));   // =>5
    console.log(add4(6));   // =>10

闭包作用

  1. 解决外部访问不到函数内部变量的问题;
  2. 局部变量会常驻在内存中;
  3. 避免使用全局变量,造成全局变量污染。

使用场景

通常当你使用只有一个方法的对象时,可以使用闭包。

闭包实用实例
通过按钮改变 body 字体大小,从而改变使用了相对单位的h1、h2 的字体大小。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        body{
            font-size: 16px;
        }
        h1{
            font-size: 1.5em;
        }
        h2{
            font-size: 1.2em;
        }
    </style>
</head>
<body>
    <h1>hello world</h1>
    <h2>hi world</h2>

    <a href="#" id="fontsize12">12</a>
    <a href="#" id="fontsize20">14</a>
    <a href="#" id="fontsize24">16</a>
</body>
<script>
// 定义行为
function changeFontSize(size){
    return function(){
        document.body.style.fontSize = size + 'px'
    }
}
// 调用外层函数,给局部变量size赋值
let size12 = changeFontSize(12)
let size20 = changeFontSize(20)
let size24 = changeFontSize(24)

// 添加触发事件
document.getElementById('fontsize12').onclick = size12 
document.getElementById('fontsize20').onclick = size20 
document.getElementById('fontsize24').onclick = size24 
</script>
</html>

使用闭包模拟私有方法

<script>
    // 定义一个立即执行函数,让其返回 3 个方法
    let Counter = (function(){
        // 初始化一个计数器,值为 0
        let num = 0
        function changeBy(val){
            num += val;
        }
        return {
            up:function(){
                changeBy(1)
            },
            down:function(){
                changeBy(-1)
            },
            value:function(){
                return num
            }
        }
    })()

    console.log(Counter.value()); // => 0
    Counter.up()
    Counter.up()
    console.log(Counter.value()); // => 2
    Counter.down()
    console.log(Counter.value()); // => 1
</script>

闭包性能考量
闭包在处理速度和内存消耗方面对脚本有负面影响。例如在创建新的对象或类时,方法通常关联到对象原型上,如果方法定义到对象的构造器中,则会导致每次创建新的对象时候,方法会被重新赋一次值。关联到原型上的方法可以被所有创建出来的对象共享。减少内存消耗,提高脚本处理速度。

你可能感兴趣的:(JavaScript,面试题,javascript)