理解JavaScript变量作用域更轻松

JavaScript本身作为一门简单的语言,就其变量作用域问题一样令不少人头晕,这主要是因为JavaScript闭包的存在。本文不打算深入讲解JavaScript变量作用域问题(其实本人也没有能力能把这一话题讲的深入些),也不讲“闭包”话题,本文只讨论最实用的JavaScript作用域知识点。

一、JavaScript作用域分类
JavaScript就两种作用域:全局(window)、函数级(function)。函数级(function)不要理解为“块级(大括号{}级)”。

二、区分及定义JavaScript全局变量与局部变量
1.1定义在所有函数最外边,使用或不使用var关键字定义的变量都是全局变量。全局变量其实被解析成window对象的一个属性,所以我们可以以“window.全局变量名”方式访问它,推荐在没有必要的情况下直接使用变量名访问。如下例子演示了全局变量定义最常见的方法:


代码如下:

var msg1='This is message 1';
msg2='This is message 2';
alert(window.msg1); //This is message 1 使用window关键字进行访问
alert(window.msg2); //This is message 2
alert(msg1); //This is message 1 省略window关键字的访问方式
alert(msg2); //This is message 2
function otherFunction(){} //其它一些函数或对象声明代码
var otherObject={};

1.2在函数内(局部变量运行时环境)一样可以定义和获取全局变量。定义的方法就是不使用var关键字,而在局部环境中亦可轻松获得全局变量内容,直接使用全局变量名引用即可。需要注意的是:如果函数内定义了与全局变量同名的局部变量,那么此时函数体将优先使用自己的局部变量,如果此时你非要使用同名的全局变量,请加上window前缀。举例如下:


代码如下:

var msg1='This is message 1';
var msg3='This is message 3';
function otherFunction()
{
msg2='This is message 2'; //不使用var关键字,其实也是定义一个全局变量
var msg3='Message 3';
alert(msg1); //This is message 1 (函数内当然可以访问到外面定义的全局变量,再深的函数嵌套一样能正确获到这个全局变量,这是JavaScript闭包的其中一种体现)
alert(msg3); //Message 3 (局部变量msg3)
alert(window.msg3); //This is message 3 (使用window前缀访问同名的全局变量msg3)
alert(this.msg3); //This is message 3 (因为otherFunction ()定义在一个全局的环境中,此时otherFunction ()的this也是指向window,所有你看到window. msg3是等于this. msg3的)
}
otherFunction();
//otherFunction函数外面定义的msg1和里面定义的msg2依然是全局变量
alert(window.msg1); //This is message 1
alert(window.msg2); //This is message 2

2.1使用var关键字,在函数体内定义的变量是局部变量,此变量能供其下面所有语句块({})及子函数使用。这个变量在这个函数里任何地方都可以访问到,但却不能在这个函数的外面“直接”访问(闭包允许间接访问,或代理访问,此知识点不在本文讨论范围)。举例如下:


代码如下:

function showMsg()
{
if (true)
{
var msg='This is message';
}
alert(msg); //This is message
}
showMsg();
alert(typeof(msg)); //undefiend
//这里在if {}大括号内定义的变量msg还能在if外showMsg()内访问到,但在showMsg()外则是无法访问的

2.2父函数的变量可以被子函数访问,但子函数的变量却不能被父函数访问,显然这与我们一开始说的函数级作用域是相吻合的。这看起来老爸爽快些,儿子吝啬些。举例如下:


代码如下:

function showMsg()
{
var MsgA='Message A';
this.setMsg=function(msg)
{
var MsgB='Message B';
alert(MsgA); //Message A (子函数setMsg()可以访问父函数showMsg()的局部变量MsgA)
}
alert(MsgB); //MsgB未定义 (在父函数中不能访问其子函数中定义的变量MsgB)
}
var sm=new showMsg();
sm.setMsg('Message string');

三、需要注意的几个地方及使用技巧
1、为了避免变量混乱或被覆盖,对于局部变量的定义一定不要忘记加上var关键字(必要时我们要变量使用完后主动释放它,即“变量名=null”),同时建议把所有变量集中定义在每个函数体内的开头位置。举例如下:


代码如下:

var msg='Message';
function showMsg()
{
var msg; //这里即使不小心使用了与全局变量一样的变量名,也不用担心覆盖同名全局变量的问题
var a;
var b;
var c;
for (a=0;a<10;a++){}
this.setMsg=function(){}
}

2、巧用匿名函数,减少命名冲突或变量污染。如下两段代码其实实现了相同的功能,而第一段代码写法自己可以在那个匿名函数内大胆用自己想用的变量名等,不用担心自己定义的变量覆盖其他人定义或自己其它地方定义的变量。


代码如下:

//定义一个匿名函数,然后把代码丢到这个匿名函数里面,能有效减少命名冲突或变量污染,这是常见JS框架的做法
(function()
{
var msg='This is message';
alert(msg);
})();
document.write(msg); //msg未定义 (匿名函数外的其它方法已无法调用msg这个变量)
//-----------------------------
var msg='This is message';
alert(msg);

3、不建议在无须实例化的函数内使用this代替window去访问全局变量。一般情况使用this关键字的函数应当作为JavaScript类来处理(我喜欢把“cls”作为类名的前缀)。以下函数如果仅当作普通函数调用一下,就不应该出现this关键字,因为这通常是去操作一个全局变量了。例子:


代码如下:

function clsMsg()
{
this.msg='This is default message';
this.showMsg=function()
{
alert(this.msg);
}
}
sMsg=new clsMsg();
sMsg.msg='This is new message';
sMsg.showMsg();

四、相关知识点指引
理解以下相关知识点有助于你更好地认识JavaScript变量作用域,本文暂不详述,随后会以单独篇幅来讲,敬请关注。
(1)理解JavaScript“预解析”(2)JavaScript闭包

(0)

相关推荐

  • 关于JavaScript中var声明变量作用域的推断

    一.迷思!由一段代码引发的疑惑 请看如下代码: 复制代码 代码如下: for(var i=0;i<3;i++) { console.log(j+","+k); for(var j=0;j<3;j++) { var k = j+1; } } console.log(i); 输出结果: undefined,undefined 3,3 3,3 3 如果你是搞c.java等语言的,可能你会不解,为何j.k这种局部变量可以被作用域外的代码访问呢? 如果JavaScript中用var声

  • ECMAscript 变量作用域总结概括

    使用var操作符声明的变量与未使用var操作符声明的变量区别 Javascript是遵循ECMAScript标准下的一个产物,自然ECMAScript的标准其要遵循 ECMAScript的变量是松散类型的,即可以用来保存任何类型的数据(未经初始化的变量,会保存一个特殊值undefined). 未使用var操作符声明 function test() { message='hi'; console.log(message); } console.log(message); 未使用var操作符声明的变

  • VBScript中变量作用域

    下午在写程序的时候,碰到个变量重定义的问题,具体是在一个函数中的两个地方定义了相同的变量,两个变量分别放在IF语句的两部分中,本来以为这两次定义在语句中不同的块,应该没有影响,然而在运行中IIS却提示变量重定义,把重复定义去掉即正确. 解决了问题之后突然想到在Fdream的blog看过一篇文章<JavaScript变量无块级作用域>,似乎这两个是差不多的,在VBScript中变量同样没有块级作用域. 再次去看了那篇文章之后我也做了下试验,得到结果:在VBScript中,函数中定义的变量的作用域

  • Javascript变量作用域详解

    变量的作用域指的是变量的可见性,而生命周期则(存活期)则是从另一个角度考察变量. JS中变量的作用域分为全局变量和局部变量,函数内定义的称为局部变量,函数外的称为全局变量.("函数外的称为全局变量"是相对的,另此处讨论的前提是用var显式声明的变量,函数内不用var定义的变量默认是全局变量,当然忽略var声明变量是不赞成的). 复制代码 代码如下: var glob = 4;//函数外声明全局变量 function fun() {     var height = 20; //函数内用

  • 有关js的变量作用域和this指针的讨论

    一.变量作用域:[P71] 这一句话说的非常精辟:"在ECMAScript中,只有两种执行环境,全局环境和函数环境,每个函数都是一个执行环境,包括嵌套函数.换句话说,其他情况下即使变量声明在一对大括号中,在括号外部仍然可以访问这些变量".以下给出例子: 复制代码 代码如下: for(var i=0; i<5; i++) { var num = 20; // 在for语句中声明的变量 } alert(num); // 在for语句外部调用变量,仍然可以得到num的值 对异常语句也同

  • javascript中的变量作用域以及变量提升详细介绍

    变量作用域"一个变量的作用域表示这个变量存在的上下文.它指定了你可以访问哪些变量以及你是否有权限访问某个变量." 变量作用域分为局部作用域和全局作用域. 局部变量(处于函数级别的作用域)不像其他对面对象的编程语言(比方说C++,Java等等),javascript没有块级作用域(被花括号包围的):当是,javascript有拥有函数级别的作用域,也就是说,在一个函数内定义的变量只能在函数内部访问或者这个函数内部的函数访问(闭包除外,这个我们过几天再写个专题). 函数级别作用域的一个例子

  • 关于javascript 回调函数中变量作用域的讨论

    1.背景 Javascript中的回调函数,相信大家都不陌生,最明显的例子是做Ajax请求时,提供的回调函数, 实际上DOM节点的事件处理方法(onclick,ondblclick等)也是回调函数. 在使用DWR的时候,回调函数可以作为第一个或者最后一个参数出现,如: JScript code function callBack(result){ } myDwrService.doSomething(param1,param2,callBack);//DWR的推荐方式 //或者 myDwrSer

  • js变量作用域及可访问性的探讨

    每一种语言都有变量的概念,变量是用来存储信息的一个元素.比如下面这个函数: 复制代码 代码如下: function Student(name,age,from)  {   this.name = name;    this.age = age;   this.from = from;    this.ToString = function()   {    return "my information is name: "+this.name+",age : "+t

  • JavaScript的变量作用域深入理解

    在学习JavaScript的变量作用域之前,我们应当明确几点: a.JavaScript的变量作用域是基于其特有的作用域链的. b.JavaScript没有块级作用域. c.函数中声明的变量在整个函数中都有定义. 1.JavaScript的作用域链 首先看下下面这段代码: 复制代码 代码如下: <script type="text/javascript" language="javascript"> var rain = 1; function rain

  • 理解JavaScript变量作用域更轻松

    JavaScript本身作为一门简单的语言,就其变量作用域问题一样令不少人头晕,这主要是因为JavaScript闭包的存在.本文不打算深入讲解JavaScript变量作用域问题(其实本人也没有能力能把这一话题讲的深入些),也不讲"闭包"话题,本文只讨论最实用的JavaScript作用域知识点. 一.JavaScript作用域分类 JavaScript就两种作用域:全局(window).函数级(function).函数级(function)不要理解为"块级(大括号{}级)&qu

  • JavaScript变量作用域及内存问题实例分析

    本文实例讲述了JavaScript变量作用域及内存问题.分享给大家供大家参考,具体如下: 学习要点: 1.变量及作用域 2.内存问题 JavaScript的变量与其他语言的变量有很大区别.JavaScript变量是松散型的(不强制类型)本质,决定了它只是在特定时间用于保存特定值的一个名字而已.由于不存在定义某个变量必须要保存何种数据类型值的规则,变量的值及其数据类型可以在脚本的生命周期内改变. 一.变量及作用域 1.基本类型和引用类型的值 ECMAScript变量可能包含两种不同的数据类型的值:

  • 深入理解JavaScript 变量对象

    目录 前言 变量对象 全局上下文中变量对象 函数上下文中的变量对象 执行过程 预编译 代码执行 总结 练习题 前言 在上节<深入 JavaScript 执行上下文栈——Web 前端进阶系列第三节>我们讲到,JavaScript 引擎执行一段可执行代码时,会创建对应的执行上下文. 对于每个执行上下文,都有三个重要属性: 变量对象(Variable object,VO) 作用域链(Scope chain) this 今天我们来重点讲解变量对象. 变量对象 变量对象是与执行上下文相关的数据作用域,存

  • javascript变量作用域使用中常见错误总结

    今天在rainweb的博客上,看到了这篇非常好的文章,觉得非常有必要分享出来,相信大家认真读完这篇文章,对js作用域的理解又会上升到一个新的台阶. 前言:javascript里变量作用域是个经常让人头痛抓狂的问题,下面通过10++个题目,对经常遇到又容易出错的情况进行了简单总结,代码样例很短很简单 题目一 复制代码 代码如下: var name = 'casper'; alert(name); //毫无疑问地输出:casper 题目二 复制代码 代码如下: alert(name); //报错:对

  • 一道关于JavaScript变量作用域的面试题

    小编觉得这道题对理解JavaScript 作用域还是很有帮助的,特此又把自己的解题思路梳理了一遍,希望对其它人有所帮助. 首先看下面试题: var arr = [1, 2, 3]; for (var i = 0, j; j = arr[i++];) { console.log(j); } console.log('---------'); console.log(i); console.log('---------'); console.log(j); console.log('--------

  • JavaScript变量作用域_动力节点Java学院整理

    在JavaScript中,用var申明的变量实际上是有作用域的. 如果一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量: 'use strict'; function foo() { var x = 1; x = x + 1; } x = x + 2; // ReferenceError! 无法在函数体外引用变量x 如果两个不同的函数各自申明了同一个变量,那么该变量只在各自的函数体内起作用.换句话说,不同函数内部的同名变量互相独立,互不影响: 'use stric

  • 浅谈Javascript变量作用域问题

    Js中的变量作用域问题: 1.没有块级作用域.Js中的变量作用域不是以{}为界的,不像C/C++/Java. 如: 复制代码 代码如下: if(true){      var name = "qqyumidi";  }               alert(name);  // 结果:qqyumidi Js会将在if中定义的变量添加到当前的执行环境中,尤其在使用for循环时需要注意与其他语言的差异. 复制代码 代码如下: for(var i=0; i<10; i++){    

  • 不同浏览器javascript变量作用域的处理方法

    1.关于prototype:这里prototype是javascript的一个特性,不是那个有名的prototype框架: var string="hello world"; try{ alert(string.phone()); }catch(e){alert(e);} String.prototype.phone=function() { return "159-10957151"; } alert(string.phone()); [Ctrl+A 全选 注:如

  • javascript 变量作用域 代码分析

    代码清单1-1 展示javascript的变量作用域的例子 //设置全局变量foo,并置为"test" var foo = "test"; //在if块中 if(true){ //将foo置为'new test' var foo = "new test"; } //如我们所见,现在foo等于'new test'了 alert(foo == "new test"); //创建一个会修改变量foo的新函数 function tes

  • Javascript 变量作用域 两个可能会被忽略的小特性

    也许有些高手早已知道了,但是我觉得这两个东西还是有一些价值的,所以拿到这里和大家分享一下吧. 有如下代码: 复制代码 代码如下: <script type="text/javascript" > function test() { with (location) { var temp = "an url"; } alert(temp); } test(); </script> 调用这个函数会输出什么呢? 也许会认为它会弹出undefined,

随机推荐