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 相关文章推荐
封装好的省市地区联动控件附下载
Aug 13 Javascript
用jquery和json从后台获得数据集的代码
Nov 07 Javascript
jQuery之排序组件的深入解析
Jun 19 Javascript
页面定时刷新(1秒刷新一次)
Nov 22 Javascript
利用javaScript实现点击输入框弹出窗体选择信息
Dec 11 Javascript
javascript写的异步加载js文件函数(支持数组传参)
Jun 07 Javascript
JavaScript严格模式禁用With语句的原因
Oct 20 Javascript
微信小程序  简单实例(阅读器)的实例开发
Sep 29 Javascript
javascript实现多张图片左右无缝滚动效果
Mar 22 Javascript
详解React Native 采用Fetch方式发送跨域POST请求
Nov 15 Javascript
Ant Design的可编辑Tree的实现操作
Oct 31 Javascript
JavaScript严格模式不支持八进制的问题讲解
Nov 07 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
延长phpmyadmin登录时间的方法
2011/02/06 PHP
php中如何使对象可以像数组一样进行foreach循环
2013/08/09 PHP
详解PHP中的PDO类
2015/07/06 PHP
yii2分页之实现跳转到具体某页的实例代码
2016/06/02 PHP
Laravel5.0+框架邮件发送功能实现方法图文与实例详解
2019/04/23 PHP
HTML5如何适配 iPhone IOS 底部黑条
2021/03/09 HTML / CSS
js中settimeout方法加参数的使用实例
2014/02/27 Javascript
javascript设计模式之解释器模式详解
2014/06/05 Javascript
node.js中的fs.ftruncate方法使用说明
2014/12/15 Javascript
JS+CSS实现简单滑动门(滑动菜单)效果
2015/09/19 Javascript
AngularJS实现在ng-Options加上index的解决方法
2016/11/03 Javascript
原生js实现无缝轮播图效果
2017/01/11 Javascript
jQuery UI Grid 模态框中的表格实例代码
2017/04/01 jQuery
Vue.js实例方法之生命周期详解
2017/07/03 Javascript
详解React 在服务端渲染的实现
2017/11/16 Javascript
Vuex 入门教程
2018/01/10 Javascript
微信小程序Echarts图表组件使用方法详解
2019/06/25 Javascript
vue.config.js常用配置详解
2019/11/14 Javascript
python轻松实现代码编码格式转换
2015/03/26 Python
Python字符串切片操作知识详解
2016/03/28 Python
详解Python如何生成词云的方法
2018/06/01 Python
对IPython交互模式下的退出方法详解
2019/02/16 Python
Python3 执行Linux Bash命令的方法
2019/07/12 Python
JetBrains PyCharm(Community版本)的下载、安装和初步使用图文教程详解
2020/03/19 Python
Python实现动态循环输出文字功能
2020/05/07 Python
彻底解决Python包下载慢问题
2020/11/15 Python
UGG雪地靴德国官网:UGG德国
2016/11/19 全球购物
秘书行业自我鉴定范文
2013/12/30 职场文书
保护环境建议书100字
2014/05/13 职场文书
行政管理专业求职信
2014/07/06 职场文书
2015年大学生入党自荐书
2015/03/24 职场文书
2015年库房管理工作总结
2015/10/14 职场文书
选择比努力更重要?这是长期以来对“努力”的最大误解
2019/07/12 职场文书
MySQL 用 limit 为什么会影响性能
2021/09/15 MySQL
mybatis-plus模糊查询指定字段
2022/04/28 Java/Android
Navicat Premium自定义 sql 标签的创建方式
2022/09/23 数据库