作用域指一个变量的作用范围。
任何变成语言都有作用域的概念,简单来说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。
JS的作用域是靠函数来形成的,也就是说一个函数的变量在函数为是不可以访问的。
变量的作用域分为两种,全局变量和局部变量。
1、全局作用域:
直接写在script 标签中的js代码,都在全局作用域。
全局作用域在页面打开时创建,在页面关闭时销毁。 //生命周期
在全局作用域中有一个全局对象window,它代表的是一个浏览器的窗口。它由浏览器创建我们可以直接使用。
在全局作用域中,创建的变量都会作为window对象的属性保存,创建的函数都会作为window对象的方法保存。
在全局作用域中的变量都是全局变量,在页面的任意的部分都可以访问的到。
例子:
var a = 10;
var b = 20;
var c = 30;
function ab() {
console.log(a+b) // 30
}
function bc(){
console.log(b+c) // 50
}
//ab()和bc()可以访问到外部的变量a、b、c的值。写在最外层函数定义的变量我们称之为全局变量。
2、局部作用域 || 函数作用域:
调用函数时创建函数作用域,函数执行完毕之后,函数作用域销毁。//生命周期
在函数作用域中也有声明提前的特性,使用var关键字声明的变量,会在函数中所有的代码执行之前被声明。
函数作用域其实就是一个小的全局作用域,只不过是生命周期短。
局部作用域和全局作用域相反,局部作用域一般只在固定的代码块内可访问到,对于函数外部是无法访问的,在函数作用域中可以访问到全局作用域的变量,在全局作用域中无法访问到函数作用域中的变量。
function A() {
var a = 10;
}
console.log(a)// Uncaught ReferenceError: a is not defined
// 全局作用域无法访问到局部作用域。
A();
a = 10;
function A() {
console.log(a)
}
A();// 10 函数作用域可以访问全局作用域。
每调用一次函数时,就会创建一个新的函数作用域,他们之间是相互独立的。
function A() {
a = 10;
}
A();
A(); //这四个A()都是相互独立的。
A();
A();
关于变量的提前声明
在函数作用域中也有声明提前的特性,使用var关键字声明的变量,会在函数中所有的代码执行之前被声明
function fun() {
console.log(f) //undefined 不会产生报错信息,因为这个函数内使用了var来声明并赋值了变量f。
var f = 10;
//如果声明变量时不使用var关键字,则变量不会被声明提前。
function A() {
console.log(a)// Uncaught ReferenceError: a is not defined
// 不使用var关键字,变量不会被声明提前;
a = 10;
}
A();
在函数作用域中如果函数内部声明变量时不使用var关键字,这个变量则会转换成全局变量。
function A() {
a = 10;
}
A();
console.log(a) //运行结果为10;
var mz = 'jay';
function A() {
console.log(mz);//undefined
var mz = 'yf';
console.log(mz);//yf
}
A();
第一个输出的是undefined,不是jay,这个算是JavaScript的一个特点了,JavaScript的函数作用域是指在函数内声明的所有变量在函数体内始终是可见的,也就是说在函数体内变量声明之前就已经可以用了。上述例子其实等同于下面这个例子:
var mz = 'jay';
function A() {
var mz; //提前声明了变量;
console.log(mz);//undefined
var mz = 'yf';
console.log(mz);//yf
}
A();
关于函数的提前声明
使用函数声明形式创建的函数 function 函数(){} 它会在所有代码执行之前就被创建,所以我们可以在函数声明前来调用函数。
fun();//返回10;
function fun() {
var a = 10;
console.log(a)
}
使用函数表达式创建的函数,不会被声明提前,所以不能再声明前调用。
fun();//返回10;
fun2(); //Uncaught TypeError: B is not a function
var fun() = function fun() {
var a = 20;
console.log(a)
}
var fun2 = function fun() {
var a = 10;
console.log(a)
}
当在函数作用域中操作一个变量时,他会在自身作用域中寻找,如果有就直接使用,如果没有,就会去它上一级作用域中去寻找,直到找到全局作用域,如果全局作用域中依然没有找到,则会报错。(作用域链)
var mz = 'jay';
function A() {
var mz = 'yf';
console.log(mz);//yf 因为函数内本身有变量 mz,是一样这里输出的mz是yf,而不是jay;
}
A();
var mz = 'jay';
function A() {
console.log(mz)
}
A(); //jay A() 没有变量mz,所以这里会往上寻找,在它的上一级里寻找到了 mz=jay
function A() {
console.log(mz);
}
A(); //返回 Uncaught ReferenceError: mz is not defined
// 因为A()里没有变量mz,全局作用域中也没有mz。
在函数作用域中如果想要访问全局变量,可以使用window对象。
var mz = 'jay';
function A() {
var mz = 'yf';
console.log(window.mz);//返回 jay
}
A();
以上为本人自己的个人理解,也借鉴了网上的其他的一些文章加以自己的一些理解。本人目前技术有限,菜鸟一只,如果错误,欢迎指出。