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 相关文章推荐
通过遮罩层实现浮层DIV登录的js代码
Feb 07 Javascript
如何在node的express中使用socket.io
Dec 15 Javascript
js实现顶部可折叠的菜单工具栏效果实例
May 09 Javascript
AngularJS入门教程之控制器详解
Jul 27 Javascript
JQuery学习总结【一】
Dec 01 Javascript
webpack入门必知必会
Jan 16 Javascript
Vue的MVVM实现方法
Aug 16 Javascript
基于Vue、Vuex、Vue-router实现的购物商城(原生切换动画)效果
Jan 09 Javascript
对VUE中的对象添加属性
Sep 18 Javascript
详解webpack之图片引入-增强的file-loader:url-loader
Oct 08 Javascript
解决iview多表头动态更改列元素发生的错误的方法
Nov 02 Javascript
探索浏览器页面关闭window.close()的使用详解
Aug 21 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 array_multisort() 函数的深入解析
2013/06/20 PHP
深入理解PHP中的empty和isset函数
2016/05/26 PHP
PHP有序表查找之插值查找算法示例
2018/02/10 PHP
NodeJS学习笔记之网络编程
2014/08/03 NodeJs
原生js实现复制对象、扩展对象 类似jquery中的extend()方法
2014/08/30 Javascript
JavaScript生成二维码图片小结
2015/12/27 Javascript
Javascript之String对象详解
2016/06/08 Javascript
JS遍历数组和对象的区别及递归遍历对象、数组、属性的方法详解
2016/06/14 Javascript
vue2 自定义动态组件所遇到的问题
2017/06/08 Javascript
Vue2.0基于vue-cli+webpack父子组件通信(实例讲解)
2017/09/14 Javascript
实现两个文本框同时输入的实例
2017/09/25 Javascript
vue v-for循环重复数据无法添加问题解决方法【加track-by='索引'】
2019/03/15 Javascript
vscode vue 文件模板的配置方法
2019/07/23 Javascript
基于Echarts图表在div动态切换时不显示的解决方式
2020/07/20 Javascript
[05:00]TI9战队采访 - Royal Never Give Up
2019/08/20 DOTA
python入门之语句(if语句、while语句、for语句)
2015/01/19 Python
简述Python中的进程、线程、协程
2016/03/18 Python
Python多进程multiprocessing用法实例分析
2017/08/18 Python
Python操作MySQL模拟银行转账
2018/03/12 Python
利用Python正则表达式过滤敏感词的方法
2019/01/21 Python
Python3基础教程之递归函数简单示例
2019/06/07 Python
python opencv 二值化 计算白色像素点的实例
2019/07/03 Python
Python绘制三角函数图(sin\cos\tan)并标注特定范围的例子
2019/12/04 Python
Django自定义全局403、404、500错误页面的示例代码
2020/03/08 Python
tensorflow从ckpt和从.pb文件读取变量的值方式
2020/05/26 Python
python如何遍历指定路径下所有文件(按按照时间区间检索)
2020/09/14 Python
Python偏函数实现原理及应用
2020/11/20 Python
CSS3之transition实现下划线的示例代码
2018/05/30 HTML / CSS
LORAC官网:美国彩妆品牌
2019/08/27 全球购物
主题婚礼策划方案
2014/02/10 职场文书
小学毕业演讲稿
2014/04/25 职场文书
1亿有多大教学反思
2014/05/01 职场文书
清正廉洁演讲稿
2014/05/22 职场文书
投资入股合作协议书
2014/10/28 职场文书
今日说法观后感
2015/06/08 职场文书
如何写观后感
2015/06/19 职场文书