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 相关文章推荐
js 跨域和ajax 跨域问题小结
Jul 01 Javascript
javascript右下角弹层及自动隐藏(自己编写)
Nov 20 Javascript
利用javascript判断文件是否存在
Dec 31 Javascript
jQuery中offset()方法用法实例
Jan 16 Javascript
javascript实用方法总结
Feb 06 Javascript
贴近用户体验的Jquery日期、时间选择插件
Aug 19 Javascript
Fundebug支持监控微信小程序HTTP请求错误的方法
Feb 21 Javascript
详解Vue+ElementUI从零开始搭建自己的网站(一、环境搭建)
Apr 30 Javascript
解决vue更新路由router-view复用组件内容不刷新的问题
Nov 04 Javascript
jquery制作的移动端购物车效果完整示例
Feb 24 jQuery
JavaScript内置对象之Array的使用小结
May 12 Javascript
TypeScript 运行时类型检查补充工具
Sep 28 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
2021年最新CPU天梯图
2021/03/04 数码科技
用PHP和ACCESS写聊天室(八)
2006/10/09 PHP
PHP 页面编码声明方法详解(header或meta)
2010/03/12 PHP
linux下为php添加curl扩展的方法
2011/07/29 PHP
php中配置文件操作 如config.php文件的读取修改等操作
2012/07/07 PHP
php获取textarea的值并处理回车换行的方法
2014/10/20 PHP
php查询操作实现投票功能
2016/05/09 PHP
laravel实现上传图片,并且制作缩略图,按照日期存放的代码
2019/10/16 PHP
Javascript new关键字的玄机 以及其它
2010/08/25 Javascript
apycom出品的jQuery精美菜单破解方法
2011/02/18 Javascript
jquery中选择块并改变属性值的方法
2013/07/31 Javascript
使用RequireJS优化JavaScript引用代码的方法
2015/07/01 Javascript
JavaScript实现的伸展收缩型菜单代码
2015/10/14 Javascript
js css实现垂直方向自适应的三角提示菜单
2016/06/26 Javascript
深入浅出 jQuery中的事件机制
2016/08/23 Javascript
JS实现数组按升序及降序排列的方法
2017/04/26 Javascript
微信小程序实现获取用户信息并存入数据库操作示例
2019/05/07 Javascript
在JavaScript中使用严格模式(Strict Mode)
2019/06/13 Javascript
Vue路由切换页面不更新问题解决方案
2020/07/10 Javascript
vue项目实现设置根据路由高亮对应的菜单项操作
2020/08/06 Javascript
在Vue中使用mockjs代码实例
2020/11/25 Vue.js
python list转dict示例分享
2014/01/28 Python
详细解析Python中的变量的数据类型
2015/05/13 Python
Python模块搜索路径代码详解
2018/01/29 Python
python实现自动登录后台管理系统
2018/10/18 Python
Django框架之DRF 基于mixins来封装的视图详解
2019/07/23 Python
python使用socket 先读取长度,在读取报文内容示例
2019/09/26 Python
Django Auth用户认证组件实现代码
2020/10/13 Python
canvas实现图片马赛克的示例代码
2018/03/26 HTML / CSS
英国最大的天然和有机产品在线零售商之一:Big Green Smile
2020/05/06 全球购物
请说出你所知道的线程同步的方法
2013/04/19 面试题
某公司Java工程师面试题笔试题
2016/03/27 面试题
优秀高中生事迹材料
2014/02/11 职场文书
乡镇领导班子四风对照检查材料
2014/09/27 职场文书
考教师资格证不要错过的4个最佳时机
2019/07/17 职场文书
教你如何使用Python开发一个钉钉群应答机器人
2021/06/21 Python