1. 闭包
概念:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域
简单理解: 闭包 = 内层函数 + 外层函数的变量
先看个简单的代码:
function outer() { const a = 1 function f() { console.log(a) } f() } outer()
闭包的基本格式
function outer() { let i = 1 function fn() { console.log(i) } return fn } const fun = outer() fun() // 1 // 外层函数使用内部函数的变量
简约写法:
// 简约写法 function outer() { let i = 1 return function() { console.log(i) } } const fun = outer() fun() // 调用fun 1 // 外层函数使用内部函数的变量
闭包应用:实现数据的私有
比如,我们要做个统计函数调用次数,函数调用一次,就++
let count = 1 function fn() { count++ console.log(`函数被调用${count}次~`) } fn() // 2 fn() // 3
但是,这个count 是个全局变量,很容易被修改
function fn(){ let count = 1 function fun(){ count++ console.log(`~函数被调用${count}次~`) } return fun } const result = fn() result() // 2 result() // 3
这样实现了数据私有,无法直接修改count
2. 变量提升
变量提升是 JavaScript 中比较“奇怪”的现象,它允许在变量声明之前即被访问(仅存在于 var 声明变量)
<script> // 访问变量 str console.log(str + 'world!') // 声明变量 str var str = 'hello' </script>
注意:
1.变量在未声明即被访问时会报语法错误
2.变量在var声明之前即被访问,变量的值为 undefined
3.let/const 声明的变量不存在变量提升
4.变量提升出现在相同作用域当中
5.实际开发中推荐先声明再访问变量
变量提升是什么流程?
先把 var 变量提升到当前作用域于最前面
只提升变量声明,不提升变量赋值
然后依次执行代码
说明:
JS初学者经常花很多时间才能习惯变量提升,还经常出现一些意想不到的bug,正因为如此,ES6 引入了块级作用域用 let 或者 const 声明变量,让代码写法更加规范和人性化。
3. 函数提升
函数提升与变量提升比较类似,是指函数在声明之前即可被调用。
// 调用函数 foo() // 声明函数 function foo() { console.log('声明之前即被调用...') }
// 不存在提升现象 bar() // 错误 Uncaught TypeError: bar is not a function at xxx.html:23:1 var bar = function() { console.log('函数表达式不存在提升现象...') }
总结:
1.函数提升能够使函数的声明调用更灵活
2.函数表达式不存在提升的现象
3.函数提升出现在相同作用域当中