你不可不知的JS面试题(第三期)

Jacquelyn38
• 阅读 1889

1、什么是闭包?

你不可不知的JS面试题(第三期)如图所示,闭包就是一个定义在函数内部的函数,其作用是将函数内部和函数外部连接起来。大家知道,作用域的问题,就是在函数内部定义的变量称为局部变量,外部取不到值。下面我们通过代码来更加详细地看一下:

 function A() {  
       let x = 1;  
       return function B() {  
           console.log(x);  
           x++;  
       }  
   }  
   console.log(A()); //直接打印返回的B  
   let b = A();  
   b(); //1  
   b(); //2  
   b(); //3

上述代码我们可以看到的是再次执行A函数的时候(其实这时候执行的是B),会打印出1,再次执行,会打印出2,再执行会打印出3。我们知道了闭包不仅可以拿到函数内部的变量,还可以保存内部的变量。

接下来,我们来看下闭包的使用场景,

for (var index = 0; index < 5; index++) {  
    setTimeout(function () {  
        console.log(index)  
    });  
}  

上面的代码段,我们会打印5个5,为啥呢?因为当我们执行for循环时,setTimeout是异步的,所以每次等for循环加完,再执行setTimeout函数,一共执行5次。另一个原因因为使用了var声明的。循环体里的index跟外部的index是存在于同一个作用域,相当于在全局定义了一次。

下面我们来使用let来声明一下。结果就不一样。分别打印0、1、2、3、4

 for (let index = 0; index < 5; index++) {  
        setTimeout(function () {  
            console.log(index)  
        });  
    }

最后,我们使用闭包也来实现一下,同样分别打印0、1、2、3、4,在外部函数每次传入实参时,也就是每次循环的值index,作用到形参i,因为setTimeout为内部函数,每次都会记录值,然后打印出来。

 for (var index = 0; index < 5; index++) {  
        (function (i) {  
            setTimeout(function () {  
                console.log(i)  
            });  
        })(index);  
    }

另一个使用场景是柯里化。下面一个问题我们将详解。

2、什么是柯里化?

是把接受多个参数的函数变换成接受一个单一参数(最初的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。你不可不知的JS面试题(第三期)

3、柯里化的好处?

  • 提高适用性

  • 延迟执行

  • 提前确认

(1)、提高适用性

我们之前使用函数都是这样写,很冗余。

function check(reg,text) {  
     return reg.test(text);  
 }  
 console.log(check(/\d+/g,'123456')) //true  
 console.log(check(/\d+/g,'abcd')) // false  
 console.log(check(/\d+/g,'r8r8r7')) // true  

那么我们通过柯里化的形式简化一下。

function check(reg) {  
     return function (text) {  
        return reg.test(text);  
     }  
 }  
 const checkNum=check(/\d+/g);  

 console.log(checkNum('123456')) //true  
 console.log(checkNum('abcd')) // false  
 console.log(checkNum('r8r8r7')) // true  

(2)、延迟执行在需要的时候再执行。

const getResult = add(1)(2)(3);  
// TODO  
getResult();  

或者

const getResult =add.bind(null,1).bind(null,2).bind(null,3);  
// TODO  
getResult();  

(3)、提前确认

之前执行一次,就不会每次都去判断了,下面举例:

 function getBindEvent(isIE) {  
     if(isIE){  
         return  function () {  
             // TODO  
             console.log(1)  
         }  
     }  
     return function () {  
            // TODO  
             console.log(0)  
     }  
 }  
 const isIE = !!window.ActiveXObject||"ActiveXObject" in window;  
 const bindEvent = getBindEvent(isIE);  
 bindEvent();

最后这里来实现下图所示:你不可不知的JS面试题(第三期)

function add() {  
    // arguments是一个类数组  
    const args = Array.prototype.slice.call(arguments); // 将参数都放在一个数组里  
    return function () {  
        // 下面的arguments与上面的不一样,下面的arguments为当前函数环境下的参数  
        if(arguments.length){ // 如果有传进来的参数  
          args.push(...arguments); // 添加到数组里  
          return arguments.callee; // 返回闭包函数自身  
        }  
        return args.reduce((n,m)=>{return n+m}); // 否则参数没传进来,就直接执行他  
    }  
}  
console.log(add(1)(2)()); // 3  
console.log(add(1,2)(3)(4)()); // 10  

本期结束,谢谢

欢迎加我微信,拉你进大佬学习群哦~


作者:Vam的金豆之路

主要领域:前端开发

我的微信:maomin9761

微信公众号:前端历劫之路

你不可不知的JS面试题(第三期)


本文转转自微信公众号前端历劫之路原创https://mp.weixin.qq.com/s/zcr3NRlrxc4JCZCq7CL2tA,如有侵权,请联系删除。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
JS 闭包(内存溢出与内存泄漏)(垃圾回收机制)
1.有关闭包定义闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量闭包的特性:函数内再嵌套函数内部函数可以引用外层的参数和变量参数和变量不会被垃圾回收机制回收
Stella981 Stella981
3年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Stella981 Stella981
3年前
JS 对象数组Array 根据对象object key的值排序sort,很风骚哦
有个js对象数组varary\{id:1,name:"b"},{id:2,name:"b"}\需求是根据name或者id的值来排序,这里有个风骚的函数函数定义:function keysrt(key,desc) {  return function(a,b){    return desc ? ~~(ak
Stella981 Stella981
3年前
HIVE 时间操作函数
日期函数UNIX时间戳转日期函数: from\_unixtime语法:   from\_unixtime(bigint unixtime\, string format\)返回值: string说明: 转化UNIX时间戳(从19700101 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式举例:hive   selec
Stella981 Stella981
3年前
JavaScript函数——闭包
闭包概念只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁例子functionouter(){varlocalVal30;returnlocalVal;}
Wesley13 Wesley13
3年前
35岁是技术人的天花板吗?
35岁是技术人的天花板吗?我非常不认同“35岁现象”,人类没有那么脆弱,人类的智力不会说是35岁之后就停止发展,更不是说35岁之后就没有机会了。马云35岁还在教书,任正非35岁还在工厂上班。为什么技术人员到35岁就应该退役了呢?所以35岁根本就不是一个问题,我今年已经37岁了,我发现我才刚刚找到自己的节奏,刚刚上路。