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 相关文章推荐
JavaScript 原型继承之构造函数继承
Aug 26 Javascript
js iframe跨域访问(同主域/非同主域)分别深入介绍
Jan 24 Javascript
jQuery+JSON+jPlayer实现QQ空间音乐查询功能示例
Jun 17 Javascript
jquery将一个表单序列化为一个对象的方法
Jan 03 Javascript
jQuery中:file选择器用法实例
Jan 04 Javascript
JS控制页面跳转时未请求要跳转的地址怎么回事
Oct 14 Javascript
Node.js下自定义错误类型详解
Oct 17 Javascript
Three.js基础部分学习
Jan 08 Javascript
js鼠标移动时禁止选中文字
Feb 19 Javascript
详解node.js搭建代理服务器请求数据
Apr 08 Javascript
利用d3.js实现蜂巢图表带动画效果
Sep 03 Javascript
详解实现vue的数据响应式原理
Jan 20 Vue.js
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将数据导入到Foxmail
2006/10/09 PHP
codeigniter自带数据库类使用方法说明
2014/03/25 PHP
PHP基于GD库的缩略图生成代码(支持jpg,gif,png格式)
2014/06/19 PHP
ThinkPHP实现带验证码的文件上传功能实例
2014/11/01 PHP
PHP中preg_match正则匹配中的/u、/i、/s含义
2015/04/17 PHP
最新版本PHP 7 vs HHVM 多角度比较
2016/02/14 PHP
Yii基于CActiveForm的Ajax数据验证用法示例
2016/07/14 PHP
PHP中的empty、isset、isnull的区别与使用实例
2019/03/22 PHP
js获取键盘按键响应事件(兼容各浏览器)
2013/05/16 Javascript
jquery动态加载js三种方法实例
2013/08/03 Javascript
jQuery功能函数详解
2015/02/01 Javascript
javascript获取元素离文档各边距离的方法
2015/02/13 Javascript
浅析jQuery Mobile的初始化事件
2015/12/03 Javascript
jquery限定文本框只能输入数字(整数和小数)
2016/01/08 Javascript
javascript 广告移动特效的实现代码
2016/06/25 Javascript
详解Javascript中DOM的范围
2017/02/13 Javascript
微信小程序 图片绝对定位(背景图片)
2017/04/05 Javascript
js遍历获取表格内数据的方法(必看)
2017/04/06 Javascript
React Native实现进度条弹框的示例代码
2017/07/17 Javascript
vue2.x数组劫持原理的实现
2020/04/19 Javascript
Python抓取框架 Scrapy的架构
2016/08/12 Python
从零开始学Python第八周:详解网络编程基础(socket)
2016/12/14 Python
python docx 中文字体设置的操作方法
2018/05/08 Python
python GUI库图形界面开发之PyQt5时间控件QTimer详细使用方法与实例
2020/02/26 Python
在vscode中启动conda虚拟环境的思路详解
2020/12/25 Python
python中remove函数的踩坑记录
2021/01/04 Python
主持人演讲稿
2014/05/13 职场文书
学生干部培训方案
2014/06/12 职场文书
2014机关党员干部“正风肃纪”思想汇报
2014/09/15 职场文书
2014年设计师工作总结
2014/11/25 职场文书
幼儿园大班个人总结
2015/02/28 职场文书
区域销售大会开幕词
2016/03/04 职场文书
假如给我三天光明:舟逆水而行,人遇挫而达 
2019/10/29 职场文书
python tkinter实现定时关机
2021/04/21 Python
GO语言异常处理分析 err接口及defer延迟
2022/04/14 Golang
输入框跟随文字内容适配宽实现示例
2022/08/14 Javascript