您的位置:首页 > Web前端 > JavaScript

javascript 高级系列之变量提升与函数提升

2017-11-10 23:55 447 查看
文章开始之前,我们来先看一段代码

变量提升

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
4000
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;


好了,关于变量提升和函数提升就讲到这里了,如果本篇文章帮助到了你,那么荣幸之至

微信搜索关注公众号 【大前端js】,回复vue教程,react教程,webpack实战等等,获得不同的视频教程,大量视频教程等你来拿;

原创不易,总结不易,手打不易,转载时请注明出处,谢谢
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息