文章开始之前,我们来先看一段代码
变量提升
console.log(a); //undefined
var a = 10;
console.log(a); //10;复制代码
为什么在变量之前打印出来是 undefind 而在之后是 10 呢?
其实真正的执行是按一下步骤执行的;
var a;
//首先会检查该作用域中有没有变量,如果有,就提到作用的顶部来;
console.log(a)
//当我们打印的时候a已经存在了,此时并未赋值,所以是undefined
a = 10;
//在我们定义赋值的地方,才会给他赋值;
console.log(a)
//此时之前已经将10赋给a了,所以a打印出来就是10了复制代码
那什么是变量提升呢?这就是变量提升;
使用var定义变量的时候,js解释器会将变量提升到该作用域的最顶部,这就是变量提升
看下一个例子:
var a = 10;
function f1(){
console.log(a); //undefined
var a = 20;
console.log(a); // 20
}
f1()复制代码
不用觉得奇怪,结果本该就是这样;同样的我们来解析一遍;
var a; //变量提升
a = 10; //赋值处赋值
function f1(){
var a; //变量提升
console.log(a) //undefined
a = 20; //赋值处赋值
console.log(a) //上面已赋值,所以结果是20
}
f1();复制代码
为什么全局作用域那里已经定了啊了,并且也赋值了,而在函数f1里面打印的还是undefined,这是因为函数形成的函数作用域,已经是一个封闭性的作用域,只要它里面存在此变量,将不会去访问外层作用域的相同变量了。
所以这也解释的通为什么函数f1里面打印的还是undefined了;
再看下面一个例子:
console.log(a); // 报错: a is not defined
a = 10;复制代码
这是为什么呢?后面明明有啊,为什么还报错了,这一点就要注意了,这里的a是直接赋值的,不是var 定义的变量,他就不存在变量提升了,所以请记住这句话
只有var命令定义的变量才存在变量提升
函数提升
同样先看下面代码
//示例一
console.log(f1()) // 10;
function f1(){
return 10;
}
console.log(f1()) // 10;
//示例二
console.log(f2()) // 报错:f2 is not a function
var f2 = function (){
return 20;
}
console.log(f2()) // 20;复制代码
示例一为什么都可以打印出来正确的答案,而示例二为什么第一个打印会报错?
对比两个函数我们不难发现,示例一中的函数是声明式函数,示例二中函数是字面量式函数;
这能说明什么吗?当然,这能说明 函数的提升只对声明式函数有效,对字面量函数无效
也就是说,声明式函数才有函数提升这个概念;
我们来解析一下上面两个函数:
//示例一
function f1(){return 10};
//函数提升是将整个函数提升到最顶部;
console.log(f1())
//10 执行到这里,函数已经存在,所以打印出来是10
console.log(f1())
//10 同样函数已经存在,能打印出正确结果 10
//----------------分割线--------------------//
//示例二
var f2;//是的,这里是个变量,所以要遵循变量提升
console.log(f2())
// 没错,在这里f2是个变量,还不是函数
//所以把他当做函数使用,当然会报错说他不是一个函数
f2 = function (){return 20}
//在这里将匿名函数赋给f2
console.log(f2())
//在此之前已经将匿名函数赋值给f2了,所以f2代表的就是这个函数
//所以自然就可以将f2作为函数来调用了复制代码
另外要强调的一句是,函数提升的优先级要高于变量提升,也就是函数会被优先放在顶部,而后才是变量
好了,这就是变量提升和函数提升,是不是感觉很简单呢,最后我们再来看一个例子;
console.log(a); //function (){return}
var a = 10;
function a(){
return 10;
}
console.log(a); // 10;复制代码
这里是不是和之前说的冲突了?解析应该是下面这样;
function a(){return 10}
//首先函数被提升到最顶部
var a
//变量名与函数名一致,但是并不会将函数a覆盖
//相反的此时的变量a将会被忽略;因为在内存中其实存的仅仅是函数名(变量名)
//不是整个函数,将函数当做变量a去存储,所以当碰到一样的变量名a的时候
//将会被忽略;
console.log(a)
//因为变量a被忽略,所以这里不会打印出来undefined,而是会打印a函数;
a = 10;
//给a赋值,将会覆盖之前的a函数,之前说过,函数a仅仅是存储为函数名a,
//将函数名a当成一个变量去存储,其实就相当于使用function定义了一个变量a
//和var 定义变量是一个概念;
console.log(a)
//这个时候a的值是10,所以打印的结果是10;复制代码
好了,关于变量提升和函数提升就讲到这里了,如果本篇文章帮助到了你,那么荣幸之至
原创不易,总结不易,手打不易,转载时请注明出处,谢谢