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 相关文章推荐
十分钟打造AutoComplete自动完成效果代码
Dec 26 Javascript
ExtJs grid行 右键菜单的两种方法
Jun 19 Javascript
JavaScript使用HTML5的window.postMessage实现跨域通信例子
Apr 11 Javascript
学习JavaScript设计模式(封装)
Nov 26 Javascript
JavaScript自定义函数实现查找两个字符串最长公共子串的方法
Nov 24 Javascript
JavaScript拖动层Div代码
Mar 01 Javascript
JS中利用localStorage防止页面动态添加数据刷新后数据丢失
Mar 10 Javascript
详解Vue2 SSR 缓存 Api 数据
Nov 20 Javascript
Element Input组件分析小结
Oct 11 Javascript
基于Vue2实现简易的省市区县三级联动组件效果
Nov 05 Javascript
vue实现搜索过滤效果
May 28 Javascript
ant-design-vue 实现表格内部字段验证功能
Dec 16 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
星际流派综述
2020/03/04 星际争霸
php学习 函数 课件
2008/06/15 PHP
php trim 去除空字符的定义与语法介绍
2010/05/31 PHP
老生常谈PHP面向对象之解释器模式
2017/05/17 PHP
javascript unicode与GBK2312(中文)编码转换方法
2013/11/14 Javascript
javascript中字符串的定义示例代码
2013/12/19 Javascript
javascript实现图片跟随鼠标移动效果的方法
2015/05/13 Javascript
javascript函数式编程程序员的工具集
2015/10/11 Javascript
详解JavaScript基于面向对象之继承实例
2015/12/16 Javascript
node.js平台下的mysql数据库配置及连接
2017/03/31 Javascript
Vue2.0基于vue-cli+webpack同级组件之间的通信教程(推荐)
2017/09/14 Javascript
vue脚手架及vue-router基本使用
2018/04/09 Javascript
微信小程序滑动选择器的实现代码
2018/08/10 Javascript
VUE引入第三方js包及调用方法讲解
2019/03/01 Javascript
微信小程序基于canvas渐变实现的彩虹效果示例
2019/05/03 Javascript
微信小程序实现搜索功能
2020/03/10 Javascript
Vue解决移动端弹窗滚动穿透问题
2020/12/15 Vue.js
下载糗事百科的内容_python版
2008/12/07 Python
python正则分组的应用
2013/11/10 Python
python轻松查到删除自己的微信好友
2016/01/10 Python
python在不同层级目录import模块的方法
2016/01/31 Python
Python数据类型详解(四)字典:dict
2016/05/12 Python
Python实现的FTP通信客户端与服务器端功能示例
2018/03/28 Python
Pandas之drop_duplicates:去除重复项方法
2018/04/18 Python
Python3通过chmod修改目录或文件权限的方法示例
2020/06/08 Python
python的json包位置及用法总结
2020/06/21 Python
python爬虫---requests库的用法详解
2020/09/28 Python
css3的@media属性实现页面响应式布局示例代码
2014/02/10 HTML / CSS
橄榄树药房:OLIVEDA
2019/09/01 全球购物
有影响力的人、名人和艺术家的官方商品:Represent
2019/11/26 全球购物
请用Java实现列出某个目录下的所有文件
2013/09/23 面试题
土木工程毕业生自荐信
2013/09/21 职场文书
重点工程汇报材料
2014/08/27 职场文书
公司领导班子群众路线四风问题对照检查材料
2014/10/02 职场文书
Jedis操作Redis实现模拟验证码发送功能
2021/09/25 Redis
直播实况, OMG破敌三路五十分钟大战神技局摩托车
2022/04/01 DOTA