爱因斯坦曾说:“提出一个问题往往比解决一个问题更重要。”
我们先来看下面这段代码会输出什么内容呢?
var a=1; f(); console.log(a); function f(){ console.log(a); var a=2; console.log(a); } //输出结果: undefined 2 1这是hoisting的经典例子,涉及到函数声明和var变量声明两种提升方式,如果对输出结果理解有困难,follow本文一起学习吧!
在参考了很多教程后,对hoisting的含义归纳如下:
变量和函数的声明都将被提升到作用域(ES5:全局作用域或函数作用域)的最顶部变量或函数可以先使用后声明只有声明被提升,而不提升初始化具体操作:当遇到<script>,js会进行预解析,将var变量声明和函数声明提升,但不会执行函数,最后再按上下文执行如下图,ES5中的变量提升包含两种:(1)var声明的变量(2)函数,而函数的提升又分为函数声明和函数表达式。
关于对ES6中新增部分(let、const、class)的变量提升,之后我们会详细讲解。
下面这段代码是用var声明变量,hoisting后会输出什么呢?
function f(){ console.log(a); var a=2; } f(); //输出结果: undefined原因是js对于var声明的变量具有变量提升的特性,将所用的变量提升到作用域的最顶部,并赋值undefined。以上代码等价于
function f(){ var a; console.log(a); a=2; } f();注:没有var声明的变量会变成全局变量,也不具备变量提升的特性。
函数的变量提升分为两种:函数声明(function+函数名)和函数表达式(将匿名函数赋值给变量),它们的提升规则和var变量声明相同,我们重点讲解函数和变量同时提升的问题。
当函数声明和变量同时提升,
console.log(f); function f(){ } var f=1; //输出结果: function f(){}当函数表达式和变量同时提升,
console.log(f); var f=function(){}; var f=1; //输出结果: undefined为什么会出现两种不同的输出结果呢?
这是因为函数提升分为两种情况:
函数声明:在提升时,会连同定义整个被提升上去,并且函数声明的优先级高于变量声明,等价于 function f(){ } console.log(f); f=1; //变量声明只进行一次,因此function f()声明后,var f=1的声明会被忽略 函数表达式:其实就是var声明的变量,因此看作是两个var变量就好了,等价于 var f; console.log(f); f = function(){}; f = 1;1. 所有声明都会被提升到作用域的最顶部
2. 同一个变量声明只进行一次
3. 变量提升的优先级:函数声明 > 函数表达式 = var声明的变量
4. 函数声明的变量提升是连同定义一起,而其余两种只提升声明、不提升初始化
本文是参考多篇博客之后总结的看法,与君共勉,如有错误欢迎指正。