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

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

局部-全局作用域

例如下面的例子中,在函数外部,找不到变量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申明的变量具有块级作用域。

例如:

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();
微信公众号
手机浏览(小程序)
0
分享到:
没有账号? 忘记密码?