文章目录
引题:
var b = 10;
(function b(){
b = 20
console.log(b)
})()
讲解几个相关知识点:
1. 变量提升
变量提升是对JavaScript中执行上下文(创建和执行)工作的一种认识
从概念的字面意义上说,“变量提升”意味着变量和函数的声明会在物理层面移动到代码的最前面,但这么说并不准确。实际上变量和函数声明在代码里的位置是不会动的,而是在编译阶段被放入内存中。
2. 函数表达式提升 (named function expression)
官网简介:
- 如果你想在函数体内部引用当前函数,则需要创建一个命名函数表达式。然后函数名称将会(且只会)作为函数体(作用域内)的本地变量。
- 被函数表达式赋值的那个变量会有一个 name 属性,如果你把这个变量赋值给另一个变量的话,这个 name 属性的值也不会改变。如果函数是一个匿名函数,那 name 属性的值就是被赋值的变量的名称(隐藏值)。如果函数不是匿名的话,那 name 属性的值就是这个函数的名称(显性值)。这对于箭头函数也同样适用(箭头函数没有名字,所以你只能赋予 name 属性一个隐性名)。
函数表达式特点:
- 标识符会在编译时提升到顶部
匿名函数特点
- 标识符无法被修改
代码版:
// 此时的 b 会被提升到顶部
function b(){
}
3. 立即执行函数(IIFE)
官网介绍:
- 包围在 圆括号运算符 () 里的一个匿名函数,这个匿名函数拥有独立的词法作用域。这不仅避免了外界访问此 IIFE 中的变量,而且又不会污染全局作用域。
- 再一次使用 () 创建了一个立即执行函数表达式,JavaScript 引擎到此将直接执行函数。
白话文版:
(function (){
})()
// 还有其他的方法可以创建立即执行函数,下面放上链接
特点
- 内边具有独立的词法作用域
4.var
特点
- 存在变量提升(上面说到了)
- 一个变量可以声明多次,后面得声明会覆盖前面得
- var作用域时函数作用域,在全局定义时,this执行window,在函数体内会单独创建,该变量时局部的
重点分析这个题引得知识点:
var b = 10;
(function b(){
b = 20
console.log(b)
})()
先看答案:
分析代码
- 代码进入预解析状态,将
var b
进行变量提升,此时b
没有被赋值(b=undefined
) (这里有人会说这里明明有个函数表达式呀,为什么没有进入变量提升,因为IIFE自带有词法作用域(我们常理解得作用域)) - 发现没有可以变量提升得时候将
b
赋值为10
,此时会将b 赋值为10(b=10
) - 碰到了立即执行函数,会执行其内边的函数
function b()
- IIFE作用域中定义b =
function b(){}
- 碰到了
b = 20
,会顺着作用域链寻找是否存在b
,发现IIFE作用域
中存在b
,将IIFE作用域
中的b
赋值为20(b=20
)(因为函数表达式特性,标识符无法被修改,所以这里执行失败) - 执行
console.log(b)
,此时的b会找IIFE中的作用域看看是否存在b,发现其内边存在,将其返回
这就是为什么console.log(b)为什么会输出function b(){}的原因了
总结知识点
- var 变量提升
- 函数表达式变量提升
- 函数表达式标识符不可被修改
- 立即执行函数内边有独立的作用域
不理解可以看这里 (超详细解析,早知道就不自己写了,直接看别人的多香呀,自己写的发现漏洞百出)