一:作用域是什么?
简单来说,作用域就是变量与函数的可访问范围,即变量和函数在超出了自己的作用域后是不会被访问到的。主要目是为了提高代码的可靠性,并且减少了一部分的命名冲突。
二:作用域的分类
在js中,作用域分为了全局作用域和局部作用域。
(一)全局作用域
在页面打开之后就会自动生成一个全局作用域,所有直接写在scrpit标签里的代码都属于全局作用域,全局作用域里面的所有元素可以在任意地方被使用,当页面关闭之后,全局作用域就会被销毁。全局作用域里有一个全局对象(window)。
在全局作用域中:
1:所有创建的变量都会作为window的属性进行保存:。
var a = 5;
console.log(window.a);//打印的是5
2:所有创建的函数都会作为window的属性进行保存。
function fn() {
console.log("我是一个函数");
}
window.fn();//此时就是在调用fn函数 和fn()效果相同 打印 我是一个函数
(二)局部作用域
在js中,只有函数才可以生成一个局部作用域,定义在局部作用域里的变量和函数是不能被与之同级的另一个局部作用域所使用的,每调用一次函数就会生成一个局部作用域,在函数执行完毕后就会销毁生成的局部作用域,每次调用函数生成的局部作用域之间是相互独立的。正是如此,假如在不同的局部作用域下定义了相同名字的变量也不会影响使用,有效的减少了命名冲突。
function fn1() {
var a = 1;
console.log(a);
}
function fn2() {
var a = 2;
console.log(a);
}
fn1();//在fn1这个局部作用域里 a的值是1 不会影响到fn2 所以打印1
fn2();//在fn1这个局部作用域里 a的值是2 不会影响到fn1 所以打印2
console.log(a);//a只会在局部作用域里起到作用,所以此时全局作用域里不能使用a 会报错
三:变量的作用域
在js中,根据全局作用域和局部作用域的划分,变量也可分为全局变量和局部变量。
(一)全局变量
1:定义:在全局作用域里声明的变量就是全局变量,全局变量的作用域就是全局作用域。全局变量可以在任何地方被使用。
2:全局变量的第一种创建方式:在全局作用域里使用var 关键字声明的变量是全局变量。
3:全局变量的第二种创建方式:在局部作用域里 不使用var关键字直接将变量进行赋值,该变量也是全局变量(非常不推荐)。
(二)局部变量
1:定义:在局部作用域声明的变量就是局部变量,局部变量的作用域就是局部作用域。局部变量只能在自己的局部作用域里使用。
2: 在函数内部使用var关键字声明的变量就是局部变量。
3:函数的形参也是局部变量。
function nu() {
var num1 = 1;
num2 = 5;
console.log(num1);
}
nu();
console.log(num2);//根据上面所说,num2此时是全局变量,所以此时可以使用
(三)全局变量和局部变量的区别
全局变量:在任何一个地方都可以使用,全局变量只有在浏览器关闭的时候才会被销毁,比较占用内存资源。
局部变量:只能在函数内部使用,当其函数被调用后,就会开辟出一个内存空间存储局部变量,当函数调用完毕后,这个内存空间会销毁,因此相比之下比全局变量更节省资源空间。
四.变量和函数的声明提升
(一)变量的声明提升
1.使用var关键字定义的变量会在预解析的时候会在最开始的时候声明(但是不会进行赋值)哪怕它写在代码块的最下方。
例:
等价于
因此此时打印的是undefined。
2.没有使用var关键字声明的变量,在预解析的时候并不会进行声明提升。
结果是
(二)函数的声明提升
1.使用function关键字声明的函数会在预解析的时候将整个函数提前(包括里面的代码块)。
例:
等价于
所以不会报错,打印结果是:我是函数。
2.使用赋值式定义的函数在预解析时只会将var声明提前,并不会把代码块也提前。
例:
相当于
结果:
因为此时只是将fn声明提升了,系统并不知道fn是个函数,所以进行fn()操作的时候,就会报错。
总的来说,作用域就是所能约束的范围,全局作用域是没有什么约束的,任何地方都可以使用。局部作用域只能由函数开辟,局部作用域的约束就是只能允许自己使用,别的作用域是不能使用的。定义在了全局作用域的变量就是全局变量,定义在了局部作用域的变量就是局部变量。变量和函数在预解析时会在各自的作用域里对有var关键字的变量进行声明提升(只提升声明,不进行赋值提升)和对有function关键字的函数进行声明提升(此时连同代码都会进行提升)。