js函数3-作用域与作用域链

Posted _oldzhang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js函数3-作用域与作用域链相关的知识,希望对你有一定的参考价值。

作用域就是指定义的变量与函数能被访问到的区域。作用域链就是指一段代码中多个作用域嵌套在一起形成的一个链条。可以把这个链条想象成多个对象组成的链表,其中每个作用域是一个对象。全局的作用域位于链表的最末端。

JS中只有函数能创建作用域,创建的作用域就能和全局作用域形成至少两个对象的作用域链,如果函数又有嵌套函数,就会形成至少三个对象的作用域链。JS定义一个全局变量时实际上是定义了全局对象的一个属性(这是ECMAScript规范),声明局部变量实际上也是声明某个对象上的一个属性,只不过这个对象我们无法引用到,这个对象应该就是在ECMAScript规范中定义的VO(变量对象),VO用于存储执行上下文中的变量 、函数声明 、函数参数,函数每次执行都会实例化一个VO对象。也正是这个VO对象形成了作用域链。JS可以使用this,window来引用全局的VO,而没有关键字来引用到函数的VO。


下面是JS作用域的几点特殊之处:

1,JS只有全局与函数两种作用域,没有块级作用域

2,函数声明会被提前到其所在作用域的顶部,变量声明也会提前,只不过声明为undefined,并未赋值

     var scope = "global";
     functioin f()
	console.log(scope);  //undefined
	var scope="local";
	console.log(scope); //local
      	

3,通过var声明的全局变量无法通过delete运算符删除,不通过var声明的js会自动创建为一个全局变量,这种通过delete是可删除的(也许不通过var声明的会放在全局VO的原型对象上,所以delete无法操作,待求证)。

作用域链:

作用域链是在函数定义时就形成了的。当定义一个函数时,它实际上保存一个作用域链,当调用这个函数时,它创建一个新的VO对象来存储它的局部变量,并将这个对象添加到保存的那个作用域链上。对于嵌套函数,每次调用外部函数时,内部函数又会重新定义一次,因此每次调用时作用域链都是不同的。


理解作用域链对with语句和闭包的理解非常重要。

比如:

with(obj)

语句;

其实就是将obj加入到当前作用域的顶端,语句中就可以直接使用obj中的属性了,而不需要obj.属性来引用。


以上是关于js函数3-作用域与作用域链的主要内容,如果未能解决你的问题,请参考以下文章

js的作用域与作用域链

Js作用域与作用域链详解

js-高级(原型与原型链作用域与作用域链闭包)

JavaScript-作用域与作用域链

作用域与作用域链

前端面试题(执行上下文与执行上下文栈作用域与作用域链闭包内存溢出与内存泄露)