作用域:指一个变量作用的范围,在 javaScript 中共有两种作用域:全局作用域和函数作用域。
全局作用域:直接编写在 script 标签里编写的 js 代码,都是在全局作用域内。全局作用域在页面打开时创建,在页面关闭时销毁。
在全局作用域内有一个全局对象window,它代表的是一个浏览器的窗口,它由浏览器创建,可以直接使用。
在全局作用域内,创建的变量都会作为window对象的属性保存,创建的函数都会作为window的方法保存。
全局作用域中的变量都是全局变量,在页面的任意位置都能访问到。
var a = 10;
console.log(a);
console.log(window.a); //a是一个变量,作为一个属性保存在window对象中,因此也可以用对象属性的方法来读取a的值
//输出:
// 10
// 10
var a = 10;
console.log(b);
//没有输出,代码会报错
//因为变量b没有定义
var a = 10;
console.log(window.b);
//输出:
// undefined
//因为这种方式是代表读取window的属性b,在js中,读取不存在的属性不会报错,只会返回undefined
function fun(){
console.log("我是fun函数");
}
fun(); //调用fun函数
window.fun(); //调用window对象的fun方法
//输出:
// 我是fun函数
// 我是fun函数
window.alert("hello"); //alert是window对象的方法
//弹窗:"hello"
函数作用域:调用函数时创建函数作用域,函数执行完毕后函数作用域销毁,每调用一次函数就会创建一个新的作用域,它们之间是相互独立的。函数作用域是整体的一个局部。
function fun(){
...
} //此时没有函数作用域产生,因为还没有调用函数
fun();
fun();
fun();
//调用了三次fun函数,开启了三个函数作用域,三个函数作用域之间相互独立
在函数作用域内可以访问到全局作用域中的变量,而在全局作用域中却无法访问到函数作用域中的变量。
var a = 10;
function fun(){
console.log(a); //在函数作用域内访问全局变量
}
fun();
//输出:10
function fun(){
var b = 20;
}
console.log(b); //在全局作用域无法访问函数作用域中的变量
//报错:变量b未定义
当在函数作用域操作一个变量时,它会先在自身作用域内寻找,如果自身有就直接使用,没有则向上一级作用域寻找(上一级作用域可以是全局作用域,也可以是函数作用域),一直到找到全局作用域为止,如果在全局作用域中也没有找到则报错。
var a = 10;
function fun(){
var a = "hello";
var b = 10;
console.log(a); //自身有a变量,直接操作自己的a变量
}
fun();
console.log(a);
//输出:"hello"
// 10
var a = 10;
function fun(){
var b = 10;
console.log(a); //自身没有a变量,找上一级作用域中是否有a,此处在全局中找到了a
}
fun();
//输出:10
var a = 10;
function fun(){
var a = "hello";
function fun2(){
console.log(a); //自身没有,向上一级寻找,上一级fun函数作用域中有a,打印出fun中的a
}
fun2();
}
fun();
//输出:"hello"
var a = 10;
function fun(){
var b = 15;
function fun2(){
console.log(a); //自身没有,向上一级寻找,上一级fun函数作用域中也没有a,再向上一级作用域中寻找,在全局中找到a,输出全局的a
}
fun2();
}
fun();
//输出:10
在函数中要访问全局变量可以使用 window对象属性的方式:
var a = 10;
function fun(){
var a = "hello";
function fun2(){
console.log(a); //访问的是自己内部的a
console.log(window.a); //访问的是全局的a
}
fun2();
}
fun();
//输出:"hello"
// 10
在函数作用域中也有声明提前的特性,使用 var 关键字声明的变量会在函数中所有的代码执行之前被声明,函数声明也会在函数中所有的代码执行之前执行。
function fun(){
console.log(a);
var a = 10;
}
fun();
//输出:undefined
var a = 33;
function fun(){
console.log(a);
var a = 10;
}
fun();
//输出:undefined
function fun(){
fun2(); //函数提前声明并创建
var a = 35;
function fun2(){
console.log("我是fun2");
}
}
fun();
//输出:"我是fun2"
在函数中,不使用var声明的变量都会成为全局变量,相当于是window.a。
var c = 33;
function fun5(){
console.log(c);
c = 10; //未使用var声明,变成全局变量a,并在此处修改了c的值
}
fun5();
console.log(c);
//输出:33
// 10
在函数中定义形参就相当于是在函数作用域中声明了变量。
var a = 23;
function fun6(a){ //相当于 var a;
console.log(a);
}
fun6(8); // a = 8
fun6(); // a = undefined ,未传递实参,没有给a赋值,所以a是undefined
//输出:6
// undefined
var a = 123;
function fun(a){ // var a ;
console.log(a);
a = 456; //因为定义了形参,所有只会赋值给参数,也就是函数内部的a,不会赋值给全局的a
}
fun();
console.log(a); //打印的是全局的a
//输出:undefined
// 123