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学习笔记(二) js对象
Oct 25 Javascript
浅谈关于JavaScript的语言特性分析
Apr 11 Javascript
jQuery中DOM操作实例分析
Jan 23 Javascript
JavaScript中的this使用详解
Jul 27 Javascript
浅谈jquery采用attr修改form表单enctype不起作用的问题
Nov 25 Javascript
javaScript实现复选框全选反选事件详解
Nov 20 Javascript
JavaScript DOM元素常见操作详解【添加、删除、修改等】
May 09 Javascript
vue.js实现插入数值与表达式的方法分析
Jul 06 Javascript
node.js之基础加密算法模块crypto详解
Sep 11 Javascript
bootstrap实现嵌套模态框的实例代码
Jan 10 Javascript
vue ssr+koa2构建服务端渲染的示例代码
Mar 23 Javascript
vue中解决微信html5原生ios虚拟键返回不刷新问题
Oct 20 Javascript
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常用ODBC函数集(详细)
2013/06/24 PHP
解析func_num_args与func_get_args函数的使用
2013/06/24 PHP
php将html转为图片的实现方法
2017/05/19 PHP
PHP PDOStatement::getAttribute讲解
2019/02/01 PHP
laravel5.2表单验证,并显示错误信息的实例
2019/09/29 PHP
php中加密解密DES类的简单使用方法示例
2020/03/26 PHP
ASP.NET jQuery 实例1(在TextBox里面创建一个默认提示)
2012/01/13 Javascript
JavaScript打印iframe内容示例代码
2013/08/20 Javascript
javascript如何使用bind指定接收者
2014/05/04 Javascript
js怎么覆盖原有方法实现重写
2014/09/04 Javascript
Angular2开发环境搭建教程之VS Code
2017/12/15 Javascript
常用的 JS 排序算法 整理版
2018/04/05 Javascript
详解如何使用node.js的开发框架express创建一个web应用
2018/12/20 Javascript
Vue指令指令大全
2019/02/09 Javascript
VUE引入第三方js包及调用方法讲解
2019/03/01 Javascript
vue中利用three.js实现全景图的完整示例
2020/12/07 Vue.js
详解Python编程中time模块的使用
2015/11/20 Python
python中执行shell的两种方法总结
2017/01/10 Python
python的paramiko模块实现远程控制和传输示例
2017/10/13 Python
python保存文件方法小结
2018/07/27 Python
对Python中for复合语句的使用示例讲解
2018/11/01 Python
Python超越函数积分运算以及绘图实现代码
2019/11/20 Python
CSS3+Sprite实现僵尸行走动画特效源码
2016/01/27 HTML / CSS
CSS3中的弹性布局em运用入门详解 1em等于多少像素
2021/02/08 HTML / CSS
StubHub智利:购买和出售您的门票
2016/11/23 全球购物
GOOD AMERICAN官网:为曲线性感而设计
2017/12/28 全球购物
简述安装Slackware Linux系统的过程
2012/01/12 面试题
2013年办公室秘书的个人自我鉴定
2013/10/24 职场文书
销售助理岗位职责
2014/02/21 职场文书
幼儿园三八妇女节活动方案
2014/03/11 职场文书
供应链金融服务方案
2014/05/25 职场文书
扬州个园导游词
2015/02/06 职场文书
房地产置业顾问岗位职责
2015/04/11 职场文书
经费申请报告范文
2015/05/18 职场文书
初三毕业感言
2015/07/31 职场文书
MySQL 如何分析查询性能
2021/05/12 MySQL