JavaScript中的变量作用域介绍


Posted in Javascript onDecember 31, 2014

对于变量的作用域(scope),C、Java等语言采取的是“block scope”的方式。与之不同,JavaScript所采取的是“function scope”的方式 — 变量的作用域仅由所处的function决定,与if、for等逻辑块无关。比如,以下这个例子展示了JavaScript中与C、Java等语言不一样的行为:

function(){

  var s = 42;//s is visible throughout function

  if (s > 3) {

    var x = "test";//x is visible throughout function

    for(var i=0; i<10; i++){

      console.log(i);

    }

    console.log(i);//i is visible throughout function

  }

  console.log(i);

  console.log(x);

}

在C、Java等“block scope”的语言中,if语句、for语句等逻辑块结束后,在这些逻辑块内部定义的变量将会被销毁。JavaScript与之不同,只要一个变量定义在某function内,那么整个function内的所有代码均可访问到该变量,即使这些代码在变量定义之前:

function(){

  console.log(a);//undefined

  var a = "test";

  console.log(a);//test

}

在上述例子中,如果function中a从未被定义,那么console.log(a)将抛出ReferenceError。当function中对a进行定义后,即使这个定义在a变量调用语句之后,对a的调用也属于合法操作(如果对a变量的定义发生在调用语句之后,那么调用语句中a变量的值为undefined)。事实上,在function内用var关键词进行定义的所有变量,其定义操作都会被提至function的开头(赋值操作依然留在var定义的那一行),这在JavaScript中称之为hoisting。比如,上述代码就等价于:

function(){

  var a;

  console.log(a);//undefined

  a = "test";

  console.log(a);//test

}

变量的作用域链

联系JavaScript中变量的储存,可以很好的理解JS中的“function scope”与hoisting。由于变量是储存在全局对象或者函数调用对象上的,因此当在function中定义变量时,无论这个变量定义在function的什么地方,这次function调用所使用的函数调用对象中必然会出现一个与此变量同名的属性。如此一来,function中的任何地方都可以访问到该变量。

涉及到函数调用,JavaScript中还有一个更有趣的概念:变量的作用域链 — 由于变量是储存在全局对象或者函数调用对象上的,因此在访问变量时,可以从多个对象上获取值。以下面的代码为例:

var x = "test";

function(){

  //level-1 function

  var x = "temp";

  function(){

    //level-2 function

    var x = "real";

    //try to access x here. x will be "real".

  }

}

在上述代码中2级函数(level-2 function)的内部,当试图访问x变量时,程序可以从3个对象上搜索相应的属性值:调用2级函数所使用的函数调用对象、调用1级函数所使用的函数调用对象、全局对象 — 根据函数定义的嵌套关系,JavaScript将生成一个由全局对象和函数调用对象所组成的对象链。访问变量时,程序将从离访问语句最近的那个对象开始搜索,如果没有搜索到,则在对象链中上一级的对象中继续进行搜索,直至全局对象。

由于这个对象链与变量的作用域有关,因此也叫做“作用域链”。

如果需要临时改变作用域链,将某个对象插入到作用域链的最前端(作为最先访问到的那个函数对象),可以使用with语句:

with(o){

  //code use properties of object o.

}

不过,在JavaScript严格模式下,with语句是被禁用的;即使在非严格模式下,也不推荐使用with语句。

Javascript 相关文章推荐
如何让easyui gridview 宽度自适应窗口改变及fitColumns应用
Jan 25 Javascript
Java/JS获取flash高宽的具体方法
Dec 27 Javascript
一个支付页面DEMO附截图
Jul 22 Javascript
jQuery选择器源码解读(五):tokenize的解析过程
Mar 31 Javascript
javascript实现下班倒计时效果的方法(可桌面通知)
Jul 10 Javascript
Centos7 中 Node.js安装简单方法
Nov 02 Javascript
值得分享的JavaScript实现图片轮播组件
Nov 21 Javascript
JS判断时间段的实现代码
Jun 14 Javascript
angularjs中$http异步上传Excel文件方法
Feb 23 Javascript
JavaScript简单实现关键字文本搜索高亮显示功能示例
Jul 25 Javascript
小程序视频或音频自定义可拖拽进度条的示例代码
Sep 30 Javascript
js实现计算器功能
Aug 10 Javascript
JavaScript中的变量定义与储存介绍
Dec 31 #Javascript
JavaScript中的操作符==与===介绍
Dec 31 #Javascript
jQuery中[attribute]选择器用法实例
Dec 31 #Javascript
JavaScript中的比较操作符&gt;、=、
Dec 31 #Javascript
javascript 操作符(~、&amp;、|、^、)使用案例
Dec 31 #Javascript
JavaScript中的逻辑判断符&amp;&amp;、||与!介绍
Dec 31 #Javascript
JavaScript中的eval()函数使用介绍
Dec 31 #Javascript
You might like
php对二维数组进行相关操作(排序、转换、去空白等)
2015/11/04 PHP
在Thinkphp中使用ajax实现无刷新分页的方法
2016/10/25 PHP
简述php环境搭建与配置
2016/12/05 PHP
PHP精确到毫秒秒杀倒计时实例详解
2019/03/14 PHP
js 键盘记录实现(兼容FireFox和IE)
2010/02/07 Javascript
可以将word转成html的js代码
2010/04/11 Javascript
一个基于jquery的图片切换效果
2010/07/06 Javascript
浅析jquery的作用与优势
2013/12/02 Javascript
文本框水印提示效果的简单实现代码
2014/02/22 Javascript
jquery插件jSignature实现手动签名
2015/05/04 Javascript
jQuery幻灯片特效代码分享--鼠标滑过按钮时切换(2)
2020/11/18 Javascript
探寻JavaScript中this指针指向
2016/04/23 Javascript
js与applet相互调用的方法
2016/06/22 Javascript
Chrome浏览器的alert弹窗禁止再次弹出后恢复的方法
2016/12/30 Javascript
JavaScript实现瀑布流图片效果
2017/06/30 Javascript
js原生代码实现轮播图的实例讲解
2017/07/28 Javascript
Angular4学习笔记之根模块与Ng模块
2017/09/09 Javascript
解决vue接口数据赋值给data没有反应的问题
2018/08/27 Javascript
webpack@v4升级踩坑(小结)
2018/10/08 Javascript
JavaScript之实现一个简单的Vue示例
2019/01/17 Javascript
js图片无缝滚动插件使用详解
2020/05/26 Javascript
Python使用htpasswd实现基本认证授权的例子
2014/06/10 Python
Python3实现生成随机密码的方法
2014/08/23 Python
Python实现提取谷歌音乐搜索结果的方法
2015/07/10 Python
轻松实现TensorFlow微信跳一跳的AI
2018/01/05 Python
tensorflow实现加载mnist数据集
2018/09/08 Python
python代码实现逻辑回归logistic原理
2019/08/07 Python
python django生成迁移文件的实例
2019/08/31 Python
CSS3 新增选择器的实例
2019/11/13 HTML / CSS
canvas进阶之贝塞尔公式推导与物体跟随复杂曲线的轨迹运动
2018/01/10 HTML / CSS
世界环境日活动总结
2015/02/11 职场文书
行政处罚事先告知书
2015/07/01 职场文书
2016年教代会开幕词
2016/03/04 职场文书
MySQL锁机制
2021/04/05 MySQL
Python 内置函数速查表一览
2021/06/02 Python
SQL Server Agent 服务无法启动
2022/04/20 SQL Server