面试官常问的关于JS的问题(闭包、回调、ES5和ES6的个人的一些东西、异步编程)
面试对于闭包的回答:
1、闭包的描述:就是一个具有做哟关于的代码块,比如一个普通的函数就是一个闭包
2、闭包的使用场景举例(就是下面闭包技术的好处)
1、函数的内部的变量,想要被外部程序使用,但是语法决定了外部不能使用,可以利用闭包解决。
2、一些临时数据,比如for循环的i的值,希望延时业务中使用,可以使用闭包把临时数据保存到局部作用域中。
3、防止变量污染,可以用闭包把一些业务变量放在局部作用域中
4、可以把一个闭包封装都原型中,这样每一个对象都可以共用闭包工具
3、闭包的看法
优点:
1、函数的内部的变量,想要被外部程序使用,但是语法决定了外部不能使用,可以利用闭包解决。
2、一些临时数据,比如for循环的i的值,希望延时业务中使用,可以使用闭包把临时数据保存到局部作用域中。
3、防止变量污染,可以用闭包把一些业务变量放在局部作用域中
4、可以把一个闭包封装都原型中,这样每一个对象都可以共用闭包工具
缺点:
1、难度比较大,新手难上手
2、闭包虽然可以解决很多问题,但是在使用不恰当的时候,会导致一些致命的问题:内存泄漏
(内存泄漏:指的是,浏览器运行网页时,就会执行JS代码,引用数据会在内存中占用内存空间。如果有一个对象创建了,而且占用了内存,却没有什么业务使用(想用却用不了),这种情况就是内存泄漏)
内存管理机制:垃圾回收机制,引用数据 (底层浏览器的代码实现的功能)
系统会定期查看JS的执行情况,观察创建的对象有没有可能会被使用,如果没有可能就释放内存,每一个对象都有人引用它,如果引用的人数为0就释放。
function fn(){ var obj={age:20} function tool(){ return obj.age } return tool } // fn() //调用完后,就释放了 var re=fn() //调用完毕,内部的obj对象没释放,因为闭包返回了tool,有人还要使用对象,所以它不能释放,这就是闭包导致的内存泄漏 re=null //解决方案
内存泄漏的解决方案:
1、尽量避开,不使用闭包,或者不同的使用场景使用对应的替代技术
2、在可能存在泄漏的地方把标识符引用null ==> re=null
4、项目中自己使用过
具有作用域的代码块就是闭包 (函数是闭包)
闭包技术的好处:通过业务点对闭包做区分
(闭包根据函数的使用场景不一样,业务不一样,可以有很多方面的回答)
1、函数内部的变量外部是无法访问的,但是可以通过返回一个闭包,外部操作闭包来间接访问函数内部的变量,闭包可以决定这个变量的操作方式——利用函数的作用域和运行时作用域的功能
function alipay() { var money=100 //这就是闭包函数,可以操作上面的money function tool() {money-=20} return tool } function meituan() { var aplitool=alipay() aplitool() } meituan()
2、函数自调用,每次调用内部的局部变量或者形参都时独立的,来保存一些临时数据(自调用函数就是闭包)—— 利用函数每次调用时的生成的独立调用栈
var arr=[] for(var i=0;i<5;i++) { (function(index){ arr[index]=function fn(){console.log(index)} })(i) } arr[2]() //2
3、利用函数的独立作用域,来生成业务代码块,内部的变量相互不冲突污染全局变量
//这样写,就让每个人的代码相互独立,不会污染别人的代码 (function () { //张三的代码 })(); (function () { //李四的代码 })(); //注意:闭包函数记得写分号,下面两者是一样的。 fn()() fn() ()
4、利用函数复用的功能,制作复用工具,参数返回值 ——回调函数
function fn(arg1) { var data="hello" arg1(data) } fn(function(a){console.log(a)}) //hello
写var和不写var 的区别
function alipay() { money = 100 //写这行代码,就是将money作为了全局变量 // var money=100 //这行代码是声明在函数内部的,所以是局部变量 } alipay() console.log(100) //100 报错