0. 故事
在JS世界里,有称为函数的房子和称为变量的居民。居民分为两类,有房子的居民和没房子的居民。有房子的居民被称为局部变量,这种变量只能在房子内活动,因为离开房子它就会死亡,只能通过房子几个前门(参数)和一个后门(返回值)与外界书信往来;没有房子外面游荡的居民称为全局变量,经常来往于房子间的前门后门传递消息。没房子的全局变量学会了穿墙法术,穿墙而过,窗墙而出,视墙为无物。
林子大了什么鸟都有,全局变量多了之后,也出现小偷和强盗,严重影响房子的安全性和保密性,也给JS世界带来了极大的不稳定。于是,JS世界定下了法规(规范),限制了没有住房的全局变量的数量。虽然房子安全了,因为局部变量无法走出函数,房子之间却没办法交流了。就在这时,高科技闭包从天而降。局部变量穿上它,就像宇航服一样,在房子外自由活动。即使房子不在了,变量仍能生存下去。于是,JS世界又恢复了往日的和平与安宁。
1. 作用域概念
作用域:变量读写范围的范围。
2. 作用域分类
- 全局变量:在函数外部定义或者声明的变量。
- 局部变量:在函数内部定义或者声明的变量。
变量的状态
- 未定义--浏览器报错
- 已定义未赋值--默认值为
undefined
- 已定义已赋值
// 定义全局变量
var outer = "我是全局变量";
// 函数定义
function ScopeFunc() {
// 定义局部变量
var inner = "我是局部变量";
alert("函数ScopeFunc内部:"+outer);
alert("函数ScopeFunc内部:"+inner );
}
// 函数调用
ScopeFunc();
alert("函数ScopeFunc外部:"+outer);
alert("函数ScopeFunc外部:"+inner );// 浏览器报错inner is not defined
- 全局变量与局部变量区别
- 定义声明位置不同,全局变量函数外定义声明,局部变量函数内定义声明。
- 作用域不同,全局变量可以在任何位置访问,局部变量函数内访问。
测验
判断下面程序输出结果
// 定义全局变量
var outer = "我是全局变量";
// 函数定义
function ScopeFunc() {
// 定义局部变量
var inner = "我是局部变量";
alert("函数ScopeFunc内部:"+outer);
alert("函数ScopeFunc内部:"+inner );
// 函数定义
function ScopeFunc2(){
var inner2 = "我是局部变量2";
alert("函数ScopeFunc2内部:"+outer);
alert("函数ScopeFunc2内部:"+inner );
alert("函数ScopeFunc2内部:"+inner2 )
}
// 函数调用
ScopeFunc2();
alert("函数ScopeFunc内部:"+inner2);
}
// 函数调用
ScopeFunc();
alert("函数ScopeFunc外部:"+outer);
3 另类的全局变量
3.1 在任何地方不使用var
声明或者定义变量。
- 函数外
// alert("在赋值前:"+outer);
outer = "我是全局变量";
alert("在赋值后:"+outer);
function ScopeFunc(){
alert("在函数ScopeFunc内:"+outer);
}
ScopeFunc();
- 函数内
// 函数声明
function ScopeFunc(){
inner = "我是全局变量";
}
// alert("函数ScopeFunc外1:"+inner);
ScopeFunc();
alert("函数ScopeFunc外2:"+inner);
3.2 在任何地方使用window.变量名
声明或者定义属性。
- 函数外
// alert("在赋值前:"+outer);
window.outer = "我是全局变量";
alert("在赋值后:"+window.outer);
function ScopeFunc(){
alert("在函数ScopeFunc内:"+window.outer);
}
ScopeFunc();
- 函数内
// 函数声明
function ScopeFunc(){
window.inner = "我是全局变量";
}
alert("函数ScopeFunc外1:"+window.inner);
ScopeFunc();
alert("函数ScopeFunc外2:"+window.inner);
注意:这两种方式可以实现在函数内部定义全局变量,但是禁止这样做。
4. 全局变量的危害
全局变量污染问题:全局变量与局部变量同名。
var outer = "我是全局变量";
function test() {
var outer = "我是局部变量";
document.write("函数test()内:"+outer+"</br>");
}
document.write("函数test()调用前:"+outer+"</br>");
test();
document.write("函数test()调用后:"+outer+"</br>");
全局变量与局部变量同名时
- 在局部变量作用域内,使用的是局部变量;
- 在局部变量作用域外,使用全局变量
测验
如下输出结果
function test(){
for(var i=0;i<10;i++){
document.write(i+" ");
}
document.write(i);
}
test();
document.write(i);
5. 闭包
闭包是定义在一个函数内部的函数,通过这个内部函数,外部就能访问函数内的局部变量。闭包可以解决全局变量带来的问题。
function test(){
var inner = "我是局部变量.";
return function(){
inner +="我出来了.";
return inner;
};
}
var func = test();
document.write(func());
闭包的缺点
不必要的闭包只会徒增内存消耗,因为闭包导致局部变量不随房子灭亡。