在js中有一部分比较难以理解,却也是在笔试过程中很容易考的,那就是变量提升和函数提升的问题,这篇文章我会就变量提升和函数提升的问题拓展一下有关js函数的知识点,包括作用域的问题,后面还会有一些小练习来判断自己是否真的搞懂了。
作用域
在js中作用域分为全局作用域和函数作用域,这里是针对用var声明的变量是全局的,还是只是在函数中可以使用,在es6中新增了两个声明变量的方法,let和var一样,都是声明变量的,不过let是在块级作用域下起作用,const是用来声明常量的,不能进行二次赋值。这里重点是变量提升,就先用var来讲解。
全局作用域
什么是全局作用域?
全局作用域是指在当前的script标签内定义的变量,所有的函数都可以使用,它在打开时创建,关闭时销毁。在全局作用域中有一个全局对象window,window是由浏览器创建的,它里面的方法所有对象都可以使用。
- 在全局作用域下创建的变量会作为window进行保存,创建的函数会作为window的方法
什么是全局作用域下的变量提升?
终于说到变量提升了,那么什么是全局作用域下的变量提升呢?看一下下面的例子:
console.log(a);//undefined
var a = 10;
console.log(a);//10
由于在js中代码执行的顺序是从上而下,所以在第一次打印的时候,要找变量a,如果没有变量提升的话应该会会报错说a没有定义,而这里输出的是undefined,说明a已经定义了,但是没有赋值。那么这就是变量提升起了作用了。需要注意的是
- 变量提升只会提升声明,而不会提升赋值,也就是说在执行第一个打印操作时,只是存在变量a,a却没有值;
- 打印结果是undefined说明变量存在,只是没有值,而如果是报错说a is not defined的话,就是没有变量a。
什么是全局作用域下的函数提升?
函数提升和变量提升是一样的道理,都是将本来应该在后面执行的代码全部放在前面,只是变量提升是提升声明;而函数提升是提升整个函数,也就是在代码还没开始执行的时候函数就会被创建。
调用在定义函数之后
console.log(a);//undegfined
var a = 10;
function fun(){
console.log(a);
}
fun();//10
这里函数调用是在定义函数之后,看不出来函数是否存在提升的情况,但这里值得一提的是,如果函数没有需要访问的变量的时候,就会去上一层找,就是这个全局的a,值是10,所以会打印10.
调用在定义函数之前
console.log(a);//undefined
fun();//undefined
var a = 10;
function fun(){
console.log(a);
}
这里函数调用是在定义函数之前,并且是在a赋值之前。首先我们来判断一下,如果没有函数提升的话会怎样,执行到fun这一行,就会发现fun没有定义,然后会报错fun is not a function;现在有了函数提升过后,执行到fun后,会去找a,而a只是定义了没有赋值,就会打印一个undefined,和第一个打印一样的结果。
函数作用域
什么是函数作用域?
函数作用域,顾名思义,就是只在函数中能够使用的变量,函数作用域和全局作用域之间的关系是函数作用域中的方法可以使用全局的变量,而全局方法不能使用函数中的便来变量,每个函数之间也是不能取到各自函数内部的值的。下面的图帮助理解一下:
每个函数作用域是相互独立的,在函数内部定义的变量是不能进行相互调用的。
什么是函数作用域下的变量提升和函数提升?
函数作用域中也存在变量提升和函数提升,这个和全局作用域下的情况是一模一样的,就是把作用域想成是全局的就可以了。
练习
var a = 123;
function fun(){
alert(a);//123
}
fun();
var a = 123;
function fun(){
alert(a);//456
var a = 456;
}
fun();
alert(a);//123
var a = 123;
function fun(){
alert(a);//123
a = 456;
}
fun();
alert(a);//456(456是因为函数内部将全局的变量a的值改变了)
var a = 123;
function fun(a){
alert(a);//123
a = 456;
}
fun(123);
alert(a);//456
var a = 123;
function fun(a){
alert(a);//undefined(undefined是因为fun在被调用的时候没有传递实参)
a = 456;
}
fun();
alert(a);//456
总结
在面试的笔试题中很容易碰到这样的题,有的可能还不只是考这个知识点,可能还会涉及到闭包之类的,或者更难以理解一点儿的this指向问题,但是不管怎样,只要知道原理,怎么考都没关系,愿大家在前端这段路上坚持走下去,加油!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。