1、什么是闭包?
- 概念
闭包是一个过程,它记住了声明scope下的变量,在别的scope下,调用函数时 ,依然可以读取到这些变量。
- 原理分析
function outer(){ let n = 1; function inner(){ console.log(n); } return inner; } const fn = outer(); fn();
以上案例,提出来的问题是:
outer
执行结束之后,函数空间消亡了,inner
的n
为什么还有值?原理是什么?在我的理解里,闭包可以想象成一个
胶囊
(persistent lexical scope data \ back pack),包裹住了变量n
粘在函数inner
上,一起返回给了fn
,在memory
中开辟一个存储空间放置这个胶囊
。如果代码中有fn
在执行,它会一直访问这个胶囊里的n
值。什么时候不再有fn
了,什么时候这个胶囊
脱落掉消亡。
- 用途
两个用途:
不污染global的变量池
和变量值的暂存
2、 let和var的区别,let的产生背景?
- 区别
这两个关键词的最关键的区别是
scope
,var
是认定的scope
不包含for
,if
等这类函数块的,let
把for
,if
等函数块认定为一个scope
。
- 目的
有一些需要在函数块中记住变量属性的表达式,ES5需要加上花括号,这样子嵌套的层级会很多。ES6的时候就发明了
let
来简化代码。
3、 var的变量提升底层原理是什么?
本质上是由JS编译过程导致的。
- 代码的执行分为两个步骤
- 对声明进行编译——为
var
或function
分配地址内存。- 执行——进行正常的赋值。
例如
var a = 2;
编译器先不会管a = 2
这一赋值步骤。它最先要做的是把var a
编译掉,而运算操作留在原地。声明在编译角度上被移动到了作用域的顶端。这就是提升的底层原理。
- 拓展话题——TDZ暂时死区
aVar
的值符合提升的原则。aLet
就有点意思了,它抛出来的错误实际上就是暂时死区错误。简单来说,从声明到到let
的运算步骤为止的这段时空被锁死,外界在此期间寻求访问,不被允许。
4、 模块化思想
- 为什么要使用模块化?
模块化思想即最小暴露原则。隐藏掉别人不需要知道的代码细节,仅提供需要使用的API。保护代码的安全性和可维护性。
- 如何模块化?
书写一段模块的要点有二:1、要使用闭包原理。2、函数至少被调用执行过一次。
方法一:工厂模式
function module(){ let text = "baz"; let publicAPI = { baz: fuction (){ console.log(text); } } return publicAPI; } var foo = module(); foo.bar();
方法二:单例模式(IIFE)
var foo = (function module(){ let text = "baz"; let publicAPI = { baz: function(){ console.log(text); } return pubilcAPI; } })(); foo.bar();