深入理解 JS 闭包的 9 大使用场景

深入理解 JS 闭包的 9 大使用场景

1 返回值(最常用)

  //以闭包的形式将 name 返回。
function fn(){
        let name = "hello"
        return function(){
            return name;
        }
    }
    let func = fn(); //调用,得到函数
console.log(func());//再次调用,输出hello
复制代码

2 函数赋值

在闭包里面给fn2函数设置值,闭包的形式把name属性记忆下来,执行会输出 hello

    let fn2;
    function fn(){
        let name= "hello"
        //将函数赋值为fn2
        fn2 = function(){
            return name;
        }
    }

    fn() // 要先执行进行赋值
    console.log(fn2());//执行输出fn2,即hello
复制代码

3 函数参数

用闭包返回一个函数,把此函数作为另一个函数的参数,在另一个函数里面执行这个函数,最终输出 hello

function fn(){
    let name = "hello"
    return function callback(){
        return name;
    }
}

let fn1 = fn() //执行函数将返回值(callback函数)赋值为fn1

function fn2(f){
    //将函数作为参数传入
    console.log(f()); //执行函数并输出
    
}

fn2(fn1)  //调用函数
复制代码

4.IIFE(自执行函数)

直接在自执行函数里面将封装的函数fn1传给fn2,作为参数调用同样可以获得结果 hello

(function(){
   let name = "hello";
   let fn1 = function(){
       return name;
   }
   //直接在自执行函数里面调用fn2,将fn1作为参数传入
    fn2(fn1)
})()

function fn2(f){
    //函数组为参数传入
    console.log(f());//执行函数,并输出
    
}
复制代码

5 循环赋值

   //每秒执行1次,分别输出1-10
    for(let i = 1;i <= 10; i++){
        (function (j) {
            setTimeout(function() {
                console.log(j);
                
            },j*1000)
        })(i)//i作为实参传入
    }
复制代码

6 getter和setter

第一次输出 hello 用setter以后再输出 world ,这样做可以封装成公共方法,防止不想暴露的属性和函数暴露在外部。

 function fn() {
     let name = "hello"
     setName = function (n) {
         name = n;
     }
     getName = function(){
         return name;
     }

 //将setName,getName作为对象的属性返回
     return {
        setName:setName,
        getName:getName
        //简写
        //setName,getName
     }
 }
 let fn1 = fn()//返回对象,属性setName和getName是两个函数
 console.log(fn1.getName());//getter
 fn1.setName('world');//setter修改闭包里面的name
 console.log(fn1.getName());//getter
 
复制代码

7.迭代器(执行一次函数往下取一个值)

let arr = ["aa",'bb','cc']
function increment(arr){
    let i = 0;
    return function(){
         //这个函数每次被执行都返回数组arr中 i下标对应的元素
        return arr[i++] || "数组遍历完毕"
    }
}

let next = increment(arr);
console.log(next()); //aa
console.log(next());//bb
console.log(next());//cc
console.log(next());//数组值已经遍历完
复制代码

8 首次区分(相同的参数,函数不会重复执行)

let fn = (function(){
 let arr=[];//用来缓存的数组
 return function(val){
     if(arr.indexOf(val)==-1){//缓存中没有则表示需要执行
         arr.push(val);//将参数push到缓存数组中
         console.log('函数被执行了',arr);
         //这里写想要执行的函数
     }else{
         console.log('此次函数不需要执行');
     }
     console.log('函数调用完打印一下,方便查看已缓存的数组:',arr);
 }
})();

fn(10);
fn(10);
fn(1000);
fn(200);
fn(1000);
复制代码

执行结果如下:

可以明显的看到首次执行的会被存起来,再次执行直接取。

9 缓存

比如求和操作,如果没有缓存,每次调用都要重复计算,采用缓存已经执行过的去查找,查找到了就直接返回,不需要重新计算

let fn = (function(){
    let cache = {} 
    let calc = function (arr) {
        let sum = 0;
        for (let i = 0; i < arr.length; i++) {
           sum+=arr[i]
            
        }
        return sum;
    }
    return function() {
        let args = Array.prototype.slice.call(arguments,0);
        let key = args.join(',')
        let result , total = cache[key];
        if(total){
            console.log('从缓存中取:',cache)//打印方便查看
          result = total;
            
        }else{
          //重新计算,并存入缓存同时赋值给result
          result = cache[key]=calc(args);
          console.log('存入缓存:',cache)//打印方便查看
      }
      return result;
    }
})();
fn(1,2,3,4,5);
fn(1,2,3,4,5);
fn(1,2,3,4,5,6);
fn(1,2,3,4,5,8);
fn(1,2,3,4,5,6);

复制代码

输出结果

参考文章

免责声明:务必仔细阅读

  • 本站为个人博客,博客所转载的一切破解、path、补丁、注册机和注册信息及软件等资源文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。

  • 本站为非盈利性站点,打赏作为用户喜欢本站捐赠打赏功能,本站不贩卖软件等资源,所有内容不作为商业行为。

  • 本博客的文章中涉及的任何解锁和解密分析脚本,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断.

  • 本博客的任何内容,未经许可禁止任何公众号、自媒体进行任何形式的转载、发布。

  • 博客对任何脚本资源教程问题概不负责,包括但不限于由任何脚本资源教程错误导致的任何损失或损害.

  • 间接使用相关资源或者参照文章的任何用户,包括但不限于建立VPS或在某些行为违反国家/地区法律或相关法规的情况下进行传播, 博客对于由此引起的任何隐私泄漏或其他后果概不负责.

  • 请勿将博客的任何内容用于商业或非法目的,否则后果自负.

  • 如果任何单位或个人认为该博客的任何内容可能涉嫌侵犯其权利,则应及时通知并提供身份证明,所有权证明至admin@proyy.com.我们将在收到认证文件后删除相关内容.

  • 任何以任何方式查看此博客的任何内容的人或直接或间接使用该博客的任何内容的使用者都应仔细阅读此声明。博客保留随时更改或补充此免责声明的权利。一旦使用并复制了博客的任何内容,则视为您已接受此免责声明.

您必须在下载后的24小时内从计算机或手机中完全删除以上内容.

您使用或者复制了本博客的任何内容,则视为已接受此声明,请仔细阅读


更多福利请关注一一网络微信公众号或者小程序

一一网络微信公众号
打个小广告,宝塔服务器面板,我用的也是,很方便,重点是免费的也能用,没钱太难了,穷鬼一个,一键全能部署及管理,送你3188元礼包,点我领取https://www.bt.cn/?invite_code=MV9kY3ZwbXo=


一一网络 » 深入理解 JS 闭包的 9 大使用场景

发表评论

发表评论

一一网络-提供最优质的文章集合

立即查看 了解详情