`

Javascript作用域浅析

阅读更多
学习任何编程语言,都逃不过理解变量的作用域。

在javascript中,变量的作用域有全局(window对象)作用域和函数调用作用域。


以下变量具有全局作用域
1. 所有在最外层定义(非函数体内定义)的变量都拥有全局作用域
2. 所有末定义直接赋值的变量,系统会自动声明为拥有全局作用域的变量
3. 所有window对象的属性拥有全局作用域


以下变量具有函数作用域
1. 在函数体内部用var定义的变量,这里要注意一点,只要是在函数里定义的变量,就算是在最后一句定义,该变量也拥有整个函数的作用域。

特别应该说明的一点是,作用域是层层包含的,最外层是全局作用域,里面可以包含函数调用作用域,函数调用作用域里面还可以再有函数作用域,下面,我们看一个简单的例子:
var scope = "global";  
 window.x = "x-global";  
   
 var f1 = function(){  
     var scope = "function1";  
     y = "y-golbal";  
     alert(scope);    //will display function1  
     alert(window.scope);  //will display global  
     alert(x);               //will display x-global  
 }  
   
 f1();  
   
 alert(scope);//will display global  
 alert(y);    //will display y-golbal 

这个例子说明了简单的全局作用域和函数作用域的区别,我们再思考一下问题,如果函数f1里面没有变量scope,而全局作用域里面有这个变量,会有什么情况呢?
var scope = "global";
var f1 = function(){
	//var scope = "function1";
	alert(scope);    //will display global
	alert(window.scope);  //will display global
}
f1();
alert(scope);//will display global

为什么会这样呢,这是由于javascript的寻找变量的机制造成的。上面己经说了,作用域是层层包含的,上面的这个例子的层次应该是这样的: 全局作用域->f1的作用域。而javascript查找一个变量时,会从当前作用域往上找,直到找到为止,所以这个例子中,先在f1的作用域找 scope,找不到,则到外层的全局作用域找,在全局作用域中找到了scope,就使用该变量,这个例子中,如果在全局作用域也找不到变量scope,则会报错。
下面我们把这个例子改一下,就会有一个很有趣的现象
var scope = "global";
var f1 = function(){
	alert(scope);    //will display undefined
	alert(this.scope);  //will display global
	var scope = "function1";  //declare scope here
}
f1();
alert(scope);//will display global

这里还是用javascript查找变量的机制来解释,首先在f1的作用域里面找,而f1定义了该变量,所以使用该变量,但是还末赋值,所以是 undefined。这里要说明一点,就是作用域内的变量不管在函数的哪里声明,javascript都会在函数运行前在作用域内包含该变量。
下面,我们再看复杂一些的例子:
var scope = "global";
var scope2 = "global-scope2"
var f1 = function(){
	var scope = "function1";
	var scope2 = "function1-scope2";
	(function(){ //function2
		var scope = "function2";
		(function(){  //function3
			alert(scope);  //will display function2
			alert(scope2);  //will display function1-scope2
		})();
		
	})();
}
f1();

下面,我们还是以javascript查找变量的机制来解释一下。首先,我们看看作用域的包含情况: 全局作用域-> f1的作用域 ->f2的作用域-> f3的作用域。对于变量scope,先在f3作用域内找,没找到,往外,在f2作用域里找到,使用该值,所以打出的值为 function2。对于scope2,先在f3找,没找到,住外,在f2找,还是没找到,再往外,在f1找,找到,使用该值,所以打出的值为 function1-scope2。

上面的函数都是在定义该函数的作用域里调用,如f3 在f2定义并调用,f1在全局作用域里定义并在全局作用域调用,那么,如果在全局作用域调用,或是在别的函数里调用f3会有什么情况呢?下面我们试一下
var scope = "global";
var scope2 = "global-scope2"

var f1 = function(){
	var scope = "function1";
	var scope2 = "function1-scope2";
	return (function(){
		var scope = "function2";
		return function(){
			alert(scope);  //will display function2
			alert(scope2);  //will display function1-scope2
		}
		
	})();
	
	
}

var f4 = function(fun)
{
	fun();
}

var f3 = f1();
f4(f3);

上面的例子我们返回f3,并在f4里面调用f3,但结果没变,为什么呢?这是因为javascript的作用域包含关系是在函数定义的时候确定的,而不是在调用的时候确定的,所以不管在哪调用f3,函数的作用域包含关系都是: 全局作用域->f1->f2->f3。不过上面的这个例子还有另外一个作用域包含关系: 全局作用域->f4的作用域。

最后,还要说明的是,javascript没有块作用域,这点跟java,c++,c#,php等都是不同的,所以在循环语句里面创建的变量也是拥有函数调用作用域或是全局作用域的,并不会有临时变量存在。

注:
1.在javascript里,函数也是可以作为数据传递的,在上面的例子里用到了函数作用数据传递
2.上面的例子用到了闭包的知识,不清楚的朋友可以了解一下相关的知识
分享到:
评论

相关推荐

    深化浅析JavaScript中的作用域和上下文_.docx

    深化浅析JavaScript中的作用域和上下文_.docx

    浅析JavaScript作用域链、执行上下文与闭包

    JavaScript 采用词法作用域(lexical scoping),函数执行依赖的变量作用域是由函数定义的时候决定,而不是函数执行的时候决定,通过本文给大家介绍JavaScript作用域链、执行上下文与闭包相关知识,感兴趣的朋友一起...

    浅析JavaScript中作用域和作用域链

    本文主要介绍了JavaScript中作用域和作用域链解析,条理分明,方便理解,这里推荐给小伙伴们,有需要的朋友可以参考下

    深入浅析JavaScript中的作用域和上下文

    javascript中的作用域(scope)和上下文(context)是这门语言的独到之处,这部分归功于他们带来的灵活性。每个函数有不同的变量上下文和作用域。这些概念是javascript中一些强大的设计模式的后盾。然而这也给开发人员...

    深入浅析javascript中的作用域(推荐)

    所谓的作用域,可以简单理解为一个可以读、写的范围(区域),有些js经验的同学可能会说:”js没有块级作用域”,js除了全局作用域外,只有函数可以创建作用域。作用域的一个好处就是可以隔离变量。 我们通过一些例子来...

    浅析JavaScript中的变量复制、参数传递和作用域链

    主要介绍了浅析JavaScript中的变量复制、参数传递和作用域链 的相关资料,需要的朋友可以参考下

    深入浅析JavaScript中数据共享和数据传递

    作用域就是起作用的区域,在同一个作用域数据可以共享,超过这个作用域就是跨作用域,就得用到数据传递了。 作用域 1.ui作用域 每一个ui文件缺省都有对应的ui.js。他们作为一个闭合的作用域。ui.js里根据ui文件里...

    浅析JavaScript声明变量

    使用var关键词声明变量的作用域是当前的执行上下文,有可能是外围函数,或者,当变量声明在函数体之外时,则为全局变量。 定义在函数体外的都属于全局变量,定义在函数体内的属于局部变量。这里的定义是指通过var...

    JavaScript中var、let、const区别浅析

    //2.let是块级作用域,函数内部使用let定义后,对函数外部无影响。 let c = 3; console.log(c) function change(){ let c = 6; console.log(c) } change(); (1)只要块级作用域于中存在let命令,它所声明的变量就绑定...

    JavaScript中闭包之浅析解读(必看篇)

    红宝书中曰:“是指有权访问另外一个函数作用域中的变量的函数。” 简单的说,JavaScript允许使用内部函数—即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明...

    深入浅析JavaScript中with语句的理解

    with语句的作用是暂时改变作用域链、减少的重复输入。 其语法结构为: with(object){ //statements } 举一个实际例子吧: with(document.forms[]){ name.value = lee king; address.value = Peking; zipcode...

    JavaScript的变量声明提升问题浅析(Hoisting)

    大家应该都只奥javascript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面。网上关于JavaScript的变量声明提升问题的文章有很多,这篇文章将再次谈谈关于这...

    JavaScript变量声明var,let.const及区别浅析

    var声明变量的作用域限制在其声明位置的上下文中 var x = 0; // x是全局变量,并且赋值为0。 console.log(typeof z); // undefined,因为z还不存在。 function a() { // 当a被调用时, var y = 2; // y被声明成...

    Javascript 引擎工作机制详解

    我们需要引入几个相关的概念:执行环境栈、全局对象、执行环境、变量对象、活动对象、作用域和作用域链等,这些概念正是JS引擎工作的核心组件。这篇文章的目的不是孤立的为你讲解每一个概念需要的朋友可以参考下

    理解Javascript_13_执行模型详解

    在《理解Javascript_12_执行模型浅析》一文中,我们初步的了解了执行上下文与作用域的概念,那么这一篇将深入分析执行上下文的构建过程,了解执行上下文、函数对象、作用域三者之间的关系。

Global site tag (gtag.js) - Google Analytics