一. 作用域
1. 全局变量与局部变量
一个变量如果定义在了一个函数里面,那么这个变量就是一个局部变量,只在这个函数里面有定义。出了这个函数,就如同没有定义过一样。
function fn(){
var a = 3; //定义在一个函数里面的变量,局部变量,只有在函数里面定义
console.log(a); //打印3
}
fn();
console.log(a); //打印a is not defined分别在函数内和函数外打印a的值,发现控制台第一次能正常打印a的值,而第二次报错:a没有被定义。
原因是a被定义在了函数fn里面,所以现在这个a变量只在函数fn里面才会生效。
如果一个变量,没有定义在任何函数中,那么它将在全部程序范围内都有定义:
也就是你在js的任何位置都能够使用它
var a = 3; //定义在全局范围内的一个变量,全局变量,在程序任何一个地方都有定义
function fn(){
console.log(a); //打印3
}
fn();
console.log(a); //打印3总结:
- 定义在函数里面的变量,叫做局部变量,只在函数里面有定义。
- 定义在全局范围内的,没有定义在任何函数里面的,叫做全局变量,全局都有定义。
2. 作用域链
当遇见一个变量时,JS引擎会从其所在的作用域依次向外层查找,查找会在找到第一个匹配的标识符的时候停止.
function outer(){
var a = 3; //a的作用域是outer
function inner(){
var b = 5; //b的作用域是inner
console.log(a); //能够正常输出3,a在本层没有定义,就往上层函数找,发现上层函数outer有定义a
console.log(b); //能够正常输出5,a在本层有定义
}
inner();
}
outer();
console.log(a); //报错,因为a的作用域outer,没有定义在全局。多层嵌套,如果有同名的变量,那么就会发生“遮蔽效应”:
var a = 2; //全局变量
function fn(){
var a = 3; //会把外层的a遮蔽,这函数内部看不见外层的a了。
console.log(a); //输出3,变量在当前作用域寻找,找到了a的定义值为5
}
fn();
console.log(a); //输出2,变量在当前作用域寻找,找到了a的定义值为1作用域链:一个变量在被使用的时候,就会在当前层去寻找它是否被定义,如果找不到,就往上一层函数里寻找,直到找到全局变量,如果全局也没有,就报错变量没有被定义。
var a = 1; //全局变量
var b = 2; //全局变量
function outer(){
var a = 3; //遮蔽了外层的a,此时a为局部变量
function inner(){
var b = 4; //遮蔽了外层的b,此时b为局部变量
console.log(a); //输出3,a现在在当前层找不到定义的,所以就上一层寻找
console.log(b); //输出4
}
inner(); //调用函数
console.log(a); //输出3
console.log(b); //输出2 b现在在当前层找不到定义的,所以就上一层寻找
}
outer(); //执行函数
console.log(a); // 输出1
console.log(b); // 输出23. 没有定义的局部变量会被定义成全局变量
// var a, 相当于在全局定义了一个a
function fn(){
a = 3; //这个a第一次赋值的时候,并没有定义a,
//所以就自动的在全局的范围定义a
}
fn();
console.log(a);这是JS的一个机制,如果遇见了一个新的标识符,从来没有被定义过,并且还赋值了:
a = 1;那么就会自动帮你在全局范围内定义var a;
所以变量最好用var定义
4.函数的参数,会默认定义为这个函数的局部变量
function fn(a,b,c,d){
// var a,b,c,d; 相当于在函数内部var四个变量,是局部变量
}a,b,c,d就是一个fn内部的局部变量,出了fn就没有定义。
5.全局变量的作用
5.1 通信,共同操作同一个变量
两个函数同时操作同一个变量,一个增加,一个减少,函数和函数通信。
var num = 0;
function add(){
num++;
}
function remove(){
num--;
}5.2 累加,重复调用函数的时候,不会重置
var num = 0;
function baoshu(){
num++;
console.log(num);
}
baoshu(); //1
baoshu(); //2
baoshu(); //3如果num定义在baoshu里面,每次执行函数就会把num重置为0:
function baoshu(){
var num = 0;
num++;
console.log(num);
}
baoshu(); //1
baoshu(); //1
baoshu(); //16.函数的定义也有作用域
//这个函数返回a的平方加b的平方
function pingfanghe(a,b){
return pingfang(a) + pingfang(b);
//返回m的平方
function pingfang(m){
return Math.pow(m,2)
}
}
// 现在相求4的平方,想输出16
pingfang(4); //报错,因为全局作用域下,没有一个函数叫做pingfang机理:
function big{
function small{
}
small(); //可以运行
}
small();
//不能运行,因为小函数定义在了大函数里面,离开大函数没有作用域。
















