JavaScript变量作用域之间的关系详解

在JavaScript中var的重要作用及详解中我们知道,var有全局变量和局部变量之分,所以一个变量是有作用域的。在全局作用域中的变量可以被局部作用域的函数引用。而函数中的变量不能拿到全局作用域中使用。可以理解为作用域之间的包含关系。全局作用域包含着局部作用域,而局部作用域在全部作用域里面,并不包含全局作用域。两个函数就分别表示着两个相互独立的作用域,同级的函数之前,即使变量名称一样,也是互不影响的。

JavaScript变量作用域之间的关系详解

文章图片
例如下面的例子中,在函数外部,找不到变量i,而可以引用全局变量j。
var j = 2; function add(){ var i = 2; console.log(i+j); } console.log(i)// ReferenceError: i is not defined add(); //4

一、提升变量JavaScript的函数有个特点,就是函数会先扫描整个函数体,把申明的变量提到函数体的开头。形成了先定义后执行的顺序。如下的例子1中,在执行函数的时候,没报错,而是输出NaN,没报错的原因其实是在输出的时候,其实已经知道j是存在的,只是没赋值。试着把var j;提到var i=1;如例子2,跟例子1这个函数没区别。所以可以知道是JavaScript函数是会把变量提到函数体的最前面,可是不会把赋值提到前面。JavaScript看到的函数其实是例子2中的函数。
所以我们在书写函数的时候,尽可能养成好的习惯,把变量手动提到函数体的前面,免得带来不必要的麻烦。
例如1:
function fun(x){ var i = 1; console.log(arguments[0]+i+j); //NaN var j = 2; } fun(10);

例子2:
//把变量j提到前面。 function fun(x){ var i = 1; var j; console.log(arguments[0]+i+j); //NaN }fun(10);

二、全局作用域无论是变量还是函数,在全局作用域中,都会被默认添加为window的属性。定义函数的时候,我们知道有两种方法,可以把一个匿名函数赋值给一个变量,所以其实这个这个变量也是window的属性。全局作用域里面的函数或者是变量都可以被全局对象window调用。
只是我们在书写的时候,把window省去了。
例如:
var i = 1; var fun = function(){ alert(i)//输出:1 }function myfun(x){ var i = 1; var j = 2; console.log(arguments[0]+i+j); //输出:13 }alert(window.i); //输出全局变量中的i window.fun(); //使用全局对象window调用函数 window.myfun(10);

三、局部作用域我们知道局部作用域里面的变量不能拿到全局作用域中使用,只限在局部作用域中使用,可是有一种情况,比如for循环中定义的变量i,i在for之外还可以被使用,如果想要定义for的局部作用域,只在for循环体中使用变量i,不给局部函数所使用,那我们需要定义块级作用域。
为了解决这个问题,ES6标准中定义了新的关键字let,使用let申明的变量具有块级作用域。
【JavaScript变量作用域之间的关系详解】例如:
function fun(){ var arr =['A','B','C']; for(var i=0; i< arr.length; i++){ console.log(arr[i])//输出A,B,C }console.log(i)//在for循环中定义的变量,输出3 }function myfun(){ var sum = 0; for(let j = 0; j< 5; j++){ sum = sum + j; } console.log(sum); //10 // console.log(i)//会报错 }fun(); myfun();

    推荐阅读