JS中全局作用域与局部作用域的理解

全局作用域与局部作用域之迷思:

这一段知识点的学习可能会让不少小伙伴头大,现将个人见解奉上,欢迎探讨。

先看一段代码:

var a = 123;
fn(a);
function fn(a){
a = 456;
}
console.log(a); //123

此时执行结果为123

原因如下:

正常来讲程序自上往下执行,小伙伴可能会向,为什么函数执行会在它被声明之前呢,这样不会报错吗?答案是不会报错。此处涉及到函数提升的问题,也就是说,虽然function是在被执行的位置之后定义,但JS实际运行时会首先将它提升到顶部,所以此处函数仍可正常执行。

运行过程分析:

1.声明变量 a = 123;

2.将变量a传递给fn并执行fn,此时函数内a的值变为456.

3.向控制台打印a,结果为123

很多同学会有疑问,函数内部对变量a进行了操作,但为什么打印结果是123而不是456呢,这要分两部分来分析:

1.全局作用域中的a与局部作用域中的a并非是同一个变量,只不过是他们的变量名称恰好相同而已,function fn(a){}小括号中的a相当于是在fn的局部作用域中声明了一个变量a,外部环境实际上是无法直接访问到这个变量的。

2在执行过程中,fn(a);  中的a是实参,也就是全局变量a,将全局变量a的值123传递到函数fn中,fn的局部变量a接收到这个数 ,然后执行a = 456,那么函数中的局部变量a的值由123就变为了456。但console.log(a);  是在全局环境中执行的,我们之前说过了,全局环境不能直接访问局部环境。所以console.log访问的仍然是全局变量a,所以打印值仍然是123。

此处将全局变量和局部变量同时命名为a可能会造成理解上的难度,我们将代码改成如下:

var a = 123;
fn(a);
function fn(b){
b = 456;
}
console.log(a); //123
console.log(b); //b is not defined


b is not defined ,说明在全局作用域中它不能被访问到。

我们再将代码小小调整一下:

var a = 123;
fn(a);
function fn(b){
b = 456;
console.log(a); //123
console.log(b); //456
}
console.log(a); //123
console.log(b); //b is not defined


实际上,全局虽然无法直接访问局部变量,但局部变量是可以向上访问它的父级的变量的,此处fn的父级即为全局作用域,所以在fn中console.log(a)时可以拿到a的值。

我们继续调整代码:

var a = 123;
fn(a);
function fn() {
a = 456;
console.log(a); //456
}
console.log(a); //456

此段代码与第一段代码的不同之处是,标红的fn()小括号中没有a,也就是说,此时fn中未对a进行声明我们便在函数中使用了它,那么此处的a便默认是全局变量,大家会发现有两个全局变量a,函数的执行是在var a =123 之后进行的,若有两个同名全局变量,后执行的会覆盖先执行的。所以两次打印结果都是456。

再来一次调整:

fn(a);
var a = 123;
function fn(){
a = 456;
console.log(a); //456
}
console.log(a); //123


我们将var a = 123 和fn(a) 互换了位置,执行结果发生了变化,此处也反应了先后顺序对执行结果的影响。

猜你喜欢

转载自blog.csdn.net/weixin_41658426/article/details/80112416