js变量的作用域详解

Posted cashin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js变量的作用域详解相关的知识,希望对你有一定的参考价值。

javascript中的变量作用域问题对一些初学前端的人来说可能是一个很头疼的问题,但是我相信,等你看完这篇文章之后你会有一个相对明确的理解

首先,我们来看看下面的两段代码输出结果分别是什么。

代码一:

var a = 1;  
function func(){  
    var a;  
    alert(a);
    a = 2;  
     alert(a);  
}  
func();

代码二:

var a = 1;  
function func(){  
    alert(a);  
    a = 2;  
    alert(a);  
}  
func();

这里就涉及到了全局变量以及局部变量的问题,代码一func()中的a只是执行了声明操作,并未赋值,所以第一次弹出的是undefined,紧接着它就对a进行了赋值操作,将2赋值给a,因此代码一的输出结果是undefined 2,代码二中因为func()这个局部作用域中在第一个alert之前是没有对a进行声明赋值操作的,所以调用的还是外部全局作用域中的a的值,所以代码二的输出结果是1 2;

我们再来看下面这段代码:

var a =1;  
function func(){  
    alert(a);  
    var a = 2;  
    alert(a);  
}  
func();  
alert(a);

它的输出值又是多少呢?1 2 1?No,并不是,结果是undefined 2 1,为什么呢?这里其实涉及到了变量的预解析。上述代码其实就相当于下面这段代码:

var a =1;  
function func(){  
    var a;      //预解析
    alert(a);  
    var a = 2;  
    alert(a);  
}  
func();  
alert(a);

 以上是作用域的黄金守则第一条:  变量的查找是就近原则,去寻找var定义的变量,当就近没有找到的时候就去查找外层。


 

我们来看下面的代码:

 var a = 10;
 function funcA(){//step-4
    alert(a);//step-5->执行alert,此时只能找到外面的a=10故弹框10
 }
 function funcB(){//step-2
     var a = 20;
     funcA();//step-3
 }
 //定义了函数没啥用,调用才是真格的所以这里是step-1
bbb();//step-1

弹出的结果是10;

接下来看这段代码:

function funcA(){
    var a=b=10;
}
funcA();
alert(a);   //直接报错,a is not defined
alert(b);

而当我把alert(a)注释的时候:

function funcA(){
    var a=b=10;
}
funcA();
//alert(a);
alert(b);    //弹出10

这是为什么呢?var a=b=10这种写法在函数内,b其实是全局变量,a当然是局部变量,执行完funcA(),在全局范围内alert(a),当然是undefined,alert(b)是10。

以上是作用域黄金守则第二条: js没有块级作用域(你可以自己闭包或其他方法实现),只有函数级作用域,函数外面的变量函数里面可以找到,函数里面的变量外面找不到。


 

var a=10;
function funcA(){
    alert(a);
    var a=20;
}
funcA();    //弹出10

 还有:传参时,基本类型传值,引用类型传引用。(但是重新赋值之后就不是这样了喔):

var a = 5;
var b = a;
b +=3;
alert(a);//5
var a = [1,2,3];
var b=a;
b.push(4);
alert(a);//[1,2,3,4];

上面代码没有问题,但是下面就不一样啦。

var a=[1,2,3,];
vae b=a;
b=[1,2,3,4];
alert(a); //[1,2,3]

因为b被重新赋值了,不指向a了。

此外,参数与变量的作用域是相似的:

var a=10;
function func(a){
    a += 3;
}
func(a);
alert(a); //10

对比上下这两个:

var a=10;
function func(a){
    a += 3;
    alert(a);
}
func(a); //13

上面是参数是基本类型,只传了值进去,下面的传个引用类型:(同样也包含重新赋值的情况)

 

var a=[1,2,3];
function func(a){
    a = [1,2,3,4];
}
func(a); 
alert(a); //[1,2,3]

 

var a=[1,2,3];
function func(a){
    a.push(4);
}
func(a); 
alert(a); //[1,2,3,4]

以上是作用域黄金守则第三条: 当参数跟局部变量重名时,优先级是等同的。

(本文引用:https://www.cnblogs.com/skylar/p/3986087.html

 

 

 

 

以上是关于js变量的作用域详解的主要内容,如果未能解决你的问题,请参考以下文章

JS作用域作用域链

JS---闭包

js全局变量与局部变量 预解析与作用域链详解

Js_闭包详解

白话JS作用域,作用域,作用链详解

详解js变量作用域及内存