前端进阶之路之:JS变量提升及函数提升详解

JS变量提升及函数提升详解

在讲JS变量及函数提升前,我们得先简单了解js的作用域;(当然,如果已经了解直接略过)
在ES5中,js只有两种形式的作用域:全局作用域和函数作用域。
-全局作用域
全局对象的作用域,任意地方都可以访问到(如果没有被函数作用域覆盖)。
(在ES6中,新增了一个块级作用域(最近的大括号涵盖的范围),但是仅限于let方式申明的变量。)
-函数作用域
整个函数范围

变量提升和函数提升原则:

    **1、所有申明都会被提升到作用域的最顶上;
 	   2、同一个变量申明只进行一次,并且因此其他申明都会被忽略;
 	   3、函数声明的优先级优于变量申明,且函数声明会连带定义一起被提升。**

1.变量提升(Variable ascension)

把变量声明提升到所在作用域的顶部,但是变量赋值不会提升。
注意:变量未声明,直接使用,输出‘变量 is not defined’。

上代码:

   console.log(a);//这里输出undefined,说明变量提升了,但赋值没有提升
   var a = 9; 

2.函数提升(Function ascension)

**
在JavaScript中函数的创建方式有三种:函数声明、函数表达式(函数字面量)、函数构造法(动态的,匿名的)。
【只有函数声明创建的函数会执行函数提升,字面量定义的函数(实质为变量+匿名函数)会执行变量提升。】**

a.函数声明

注意,函数提升与变量提升不同的是,函数提升会将函数声明连带定义一起提升。
看代码

console.log(fun());//这里输出2,读到了函数体,说明函数声明和函数定义都提升了
function fn(){
	return 2;

b.函数表达式(函数字面量,也叫作匿名函数)

console.log(fn);//输出undefined
console.log(fn());//报错,fn不是一个函数,此时fn就相当于一个保存函数地址的变量
var fn = function(){
return 2;
}

c.函数构造法(动态的,匿名的)

console.log(fn);//输出undefined,这里的函数提升方式和上面的字面量几乎相同
var fn = new Function("console.log(1);");

3.函数与变量同名

a.-如果变量名和函数名重名,则保留函数名;(同一个标识符的情况下,变量声明与函数声明会都会提升;

console.log(typeof fn);//输出 function,表示保留了函数提升
var fn = 2;
function fn(){
 	console.log(1);
 }

** b.函数声明会覆盖变量声明,但不会覆盖变量赋值,即:如果声明变量的同时初始化或赋值,那么变量优先级高于函数);**

console.log(typeof fn);//输出 function
var fn = 2;
function fn(){
 	console.log(1);
 }
console.log(typeof fn);// 输出 number

这里与上面不同的是,在最后一行输出了fn的类型,结果是number,说明保留的是变量fn
为何会这样呢?
实际上,这是由于这时程序已经加载完var fn = 2;这行代码,变量fn此时已经被赋值(或者叫初始化),所有这个时候变量的优先级会高于函数

4.在if/else语句里,函数/变量的提升方式

-在if/else语句里,函数声明成为了函数表达式,表达式在预编译里不提前,但是变量声明会提升,此时会将函数名当作变量名提升;

console.log(typeof fn);//输出undefined 而不是function
if(true){
      function fn(){
          console.log(1);
      }
}

这里的fn被解析为一个没被赋值的变量名,而不是一个函数

总结

a.-变量提升
把变量声明提升到函数的顶部,但是变量赋值不会提升。
注意:变量未声明,直接使用,输出‘变量 is not defined’。
b.-函数提升
函数提升会将函数声明连带定义一起提升。
在JavaScript中函数的创建方式有三种:函数声明、函数表达式(函数字面量)、函数构造法(动态的,匿名的)。
【只有函数声明创建的函数会执行函数提升,字面量定义的函数(实质为变量+匿名函数)会执行变量提升。】
c.-如果变量名和函数名重名,则保留函数名;(同一个标识符的情况下,变量声明与函数声明会都会提升;
函数声明会覆盖变量声明,但不会覆盖变量赋值,即:如果声明变量的同时初始化或赋值,那么变量优先级高于函数);
d.-在if/else语句里,函数声明成为了函数表达式,表达式在预编译里不提前,但是变量声明会提升,此时会将函数名当作变量名提升;

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值