JavaScript变量的作用域全解析


Posted in Javascript onAugust 14, 2015

变量作用域是程序中定义这个变量的区域。
先来看一段示例:

/*  代码1  */

var scope = "global ";
function checkScope() {
 var scope = "local ";
 function childCheck() {
  var scope = "childLocal ";
  document.write(scope);
 }
 function childUndefined() {
  document.write(scope);
  var scope;
 }
 function childOverride() {
  scope = "childOverride ";
  document.write(scope);
 }
 document.write(scope); //输出"local"
 childCheck();   //输出"childLocal"
 childUndefined();  //输出"undefined"
 childOverride();  //输出"childOverride"
 document.write(scope); //输出"childOverride"
}
checkScope();    //输出"local childLocal undefinedchildOverride childOverride"
document.write(scope);  //输出"global "

全局作用域与局部作用域
全局(global)变量的作用域是全局的,在Javascript中处处有定义;而函数内部声明的变量是局部(local)变量,其作用域是局部性的,只在函数体内部有定义。对于下面的输出读者应不会感到意外。
/*  代码2  */

var scope = "global";
function checkScope() {
 var scope = "local";
 document.write(scope);
}
checkScope();   //输出"local"
document.write(scope); //输出"global"

全局变量作用域中使用变量可以不用var语句,但在声明局部变量是一定要使用var语句,否则会视为对全局变量的引用。看下面代码:
/*  代码3  */

var scope = "global";
function checkScope() {
 scope = "local";
 document.write(scope);
}
checkScope();   //输出"local"
document.write(scope); //输出"local"

没有块作用域
Javascript没有块级作用域,函数中声明的变量在整个函数中都是有定义的。对于下面的代码对于生疏的读者可能颇感意外:
/*  代码4  */

var scope = "global";
function checkScope() {
 document.write(scope); //语句4.1
 var scope = "local"; //语句4.2
 document.write(scope);
}
checkScope();   //输出"undefinedlocal"

由于语句4.1(var scope = "local";)声明的变量在整个checkScope函数作用域内都有效,因此在语句4.2(document.write(scope); )执行的时scope引用的是局部变量,而此时局部变量scope尚未定义,所以输出”undefined”。因此一个好的编程习惯是将所有的变量声明集中起来放在函数的开头。

在了解了上述内容之后,读者再看看代码1应该不会感到困惑了。
对象的属性变量
对象的属性变量比较容易理解,看一下下面的代码读者应该不会感到疑惑。
/*  代码5  */

var scope = "global ";
var obj = new Object();
obj.scope = "object ";
obj.checkScope = function () {
 var scope = "loacl ";
 document.write(scope);   //输出"loacl"
 document.write(this.scope);  //输出"object"
 document.write(window.scope); //输出"global"
}
obj.checkScope(); //输出"loacl object global"

所谓作用域,就是说这个变量在代码块中的有效范围。如果不理解 JavaScript 作用域,调试代码的时候可能会比较困难。

在函数中,如果用var来声明一个变量,那么该变量的作用域就只限于该函数内部,函数外的代码无法访问该变量。如果在该函数中再声明一个函数,那么这个内部的函数也可以访问这个变量。

反过来,如果声明变量的时候没有用var,那么此变量的作用域就不局限于这个函数了。JavaScript 引擎会再全局范围中检查该变量是否被定义过。如果该变量没有被定义过,那么它就会被定义为一个全局变量。

函数可以访问相同作用域中的变量:

var foo = 'hello';

var sayHello = function() {
 console.log(foo);
};

sayHello();   // logs 'hello'
console.log(foo); // also logs 'hello'

变量作用域之外的代码不能访问该变量:

var sayHello = function() {
 var foo = 'hello';
 console.log(foo);
};

sayHello();   // logs 'hello'
console.log(foo); // doesn't log anything

不用作用域中名称相同的变量,有不同的值:

var foo = 'world';

var sayHello = function() {
 var foo = 'hello';
 console.log(foo);
};

sayHello();   // logs 'hello'
console.log(foo); // logs 'world'

函数定以后可以看到函数内变量值的改变:

var myFunction = function() {
 var foo = 'hello';

 var myFn = function() {
  console.log(foo);
 };

 foo = 'world';

 return myFn;
};

var f = myFunction();
f(); // logs 'world' -- haha

作用域也会穿越 — 闭包

// 一个自执行的匿名函数
(function() {
 var baz = 1;
 var bim = function() { alert(baz); };
 bar = function() { alert(baz); };
})();

console.log(baz); // 在函数外面不能访问 baz

bar(); // 声明 bar 的时候并没有用 var
  // 所以 bar 是一个全局变量; 但是,
  // bar 和 baz 在相同的作用域内被定义,
  // 所以 bar 可以访问 baz
  // 其实 bar 是个闭包函数

bim(); // bim 的作用域只限于匿名函数内部,
  // 所以这里不能调用

综合

所谓作用域,就是说这个变量在代码块中的有效范围。如果不理解 JavaScript 作用域,调试代码的时候可能会比较困难。

在函数中,如果用var来声明一个变量,那么该变量的作用域就只限于该函数内部,函数外的代码无法访问该变量。如果在该函数中再声明一个函数,那么这个内部的函数也可以访问这个变量。

反过来,如果声明变量的时候没有用var,那么此变量的作用域就不局限于这个函数了。JavaScript 引擎会再全局范围中检查该变量是否被定义过。如果该变量没有被定义过,那么它就会被定义为一个全局变量。

函数可以访问相同作用域中的变量:

var foo = 'hello';

var sayHello = function() {
 console.log(foo);
};

sayHello();   // logs 'hello'
console.log(foo); // also logs 'hello'

变量作用域之外的代码不能访问该变量:

var sayHello = function() {
 var foo = 'hello';
 console.log(foo);
};

sayHello();   // logs 'hello'
console.log(foo); // doesn't log anything

不用作用域中名称相同的变量,有不同的值:

var foo = 'world';

var sayHello = function() {
 var foo = 'hello';
 console.log(foo);
};

sayHello();   // logs 'hello'
console.log(foo); // logs 'world'

函数定以后可以看到函数内变量值的改变:

 
var myFunction = function() {
 var foo = 'hello';

 var myFn = function() {
  console.log(foo);
 };

 foo = 'world';

 return myFn;
};

var f = myFunction();
f(); // logs 'world' -- haha

作用域也会穿越 — 闭包

// 一个自执行的匿名函数
(function() {
 var baz = 1;
 var bim = function() { alert(baz); };
 bar = function() { alert(baz); };
})();

console.log(baz); // 在函数外面不能访问 baz

bar(); // 声明 bar 的时候并没有用 var
  // 所以 bar 是一个全局变量; 但是,
  // bar 和 baz 在相同的作用域内被定义,
  // 所以 bar 可以访问 baz
  // 其实 bar 是个闭包函数

bim(); // bim 的作用域只限于匿名函数内部,
  // 所以这里不能调用
Javascript 相关文章推荐
JavaScript具有类似Lambda表达式编程能力的代码(改进版)
Sep 14 Javascript
jquery全选checkBox功能实现代码(取消全选功能)
Dec 10 Javascript
jQuery选择器源码解读(八):addCombinator函数
Mar 31 Javascript
JS中处理时间之setUTCMinutes()方法的使用
Jun 12 Javascript
AngularJS基础 ng-repeat 指令简单示例
Aug 03 Javascript
JavaScript拖动层Div代码
Mar 01 Javascript
jQuery插件Echarts实现的渐变色柱状图
Mar 23 jQuery
对angular 实时更新模板视图的方法$apply详解
Oct 09 Javascript
原生js实现trigger方法示例代码
May 22 Javascript
uni-app 支持多端第三方地图定位的方法
Jan 03 Javascript
javascript设计模式 ? 外观模式原理与用法实例分析
Apr 15 Javascript
Jquery+AJAX实现无刷新上传并重命名文件操作示例【PHP后台接收】
May 29 jQuery
DEDECMS如何为文章添加HOT NEW标志图片
Aug 14 #Javascript
JavaScript实现给按钮加上双重动作的方法
Aug 14 #Javascript
详解jQuery中的元素的属性和相关操作
Aug 14 #Javascript
js实现人才网站职位选择功能的方法
Aug 14 #Javascript
jQuery入门基础知识学习指南
Aug 14 #Javascript
Jquery全选与反选点击执行一次的解决方案
Aug 14 #Javascript
js实现Select列表各项上移和下移的方法
Aug 14 #Javascript
You might like
PHP 配置文件中open_basedir选项作用
2009/07/19 PHP
php生成excel文件的简单方法
2014/02/08 PHP
PHP实现的多维数组排序算法分析
2018/02/10 PHP
如何屏蔽防止别的网站嵌入框架代码
2015/08/24 Javascript
JQuery中attr属性和jQuery.data()学习笔记【必看】
2016/05/18 Javascript
基于bootstrap实现广告轮播带图片和文字效果
2016/07/22 Javascript
简单的js计算器实现
2016/10/26 Javascript
使用JavaScript获取URL中的参数(两种方法)
2016/11/16 Javascript
学习 NodeJS 第八天:Socket 通讯实例
2016/12/21 NodeJs
一个Vue页面的内存泄露分析详解
2018/06/25 Javascript
11个教程中不常被提及的JavaScript小技巧(推荐)
2019/04/17 Javascript
浅谈vue 多个变量同时赋相同值互相影响
2020/08/05 Javascript
vue设置全局访问接口API地址操作
2020/08/14 Javascript
Webpack3+React16代码分割的实现
2021/03/03 Javascript
Python使用Srapy框架爬虫模拟登陆并抓取知乎内容
2016/07/02 Python
对python .txt文件读取及数据处理方法总结
2018/04/23 Python
Python 中的lambda函数介绍
2018/10/10 Python
Python操作rabbitMQ的示例代码
2019/03/19 Python
python opencv minAreaRect 生成最小外接矩形的方法
2019/07/01 Python
简单了解python中对象的取反运算符
2019/07/01 Python
详解Anaconda 的安装教程
2020/09/23 Python
使用PyCharm官方中文语言包汉化PyCharm
2020/11/18 Python
CSS3实现银灰色动画效果的导航菜单代码
2015/09/01 HTML / CSS
高三自我鉴定
2013/10/23 职场文书
小学班干部竞选演讲稿
2014/04/24 职场文书
贷款承诺书范文
2014/05/19 职场文书
技术入股合作协议书
2014/10/07 职场文书
精神文明建设汇报材料
2014/12/24 职场文书
本科毕业论文导师评语
2014/12/31 职场文书
毕业生评语大全
2015/01/04 职场文书
拾金不昧表扬稿
2015/01/16 职场文书
项目验收申请报告
2015/05/15 职场文书
驳回起诉裁定书
2015/05/19 职场文书
使用Python的开发框架Brownie部署以太坊智能合约
2021/05/28 Python
NASA 机智号火星直升机拍到了毅力号设备碎片
2022/04/29 数码科技
讲解Python实例练习逆序输出字符串
2022/05/06 Python