变量作用域&函数作用域

时间:2021-03-23 06:23:07

一. 变量作用域

1)全局变量

在全局环境下声明的变量被视为全局变量。

在没有使用var进行声明的时候,变量就被定义为全局变量。在ES5的严格模式下,如果变量没有使用var来声明是会报错的。

2)局部变量

在函数体内部声明的变量被视为局部变量。其中涉及到js中的函数作用域问题。

二. 函数作用域

因为js中是没有块级作用域的概念,所谓的块级作用域就是指花括号内的的每一段代码都有其自己的作用域,但js中并不是,例如for循环中定义的变量,外界也可以访问;但是js中有函数作用域的概念,即在每一个函数体内,变量是有其自己的作用域的,外界访问不到;

三. 变量提升

js在编译阶段有个特性,就是变量提升。当js引擎在解析代码的时候,会将变量声明提升至其函数体的顶部。有关资料可参考

http://www.slideshare.net/lijing00333/javascript-engine

借用ppt里的例子:

a();
function a () {

alert('Tom');
}

var a = function () { 
alert('Jim');
} a();

执行时会先弹出Tom,再弹出Jim。具体的过程是,js是解释型语言,因此当浏览器运行js时会分为两个部分,首先预编译全部代码,之后执行代码。

变量作用域&函数作用域

变量作用域&函数作用域

下面的例子:

a();
function a () {
alert('1');
}
a();
function a () {
alert('2');
}
a();
var a = function () {
alert('3');
}
a();

此处同理,会弹出2,2,2,3,只不过在编译阶段,后面的函数a声明覆盖了前面的声明,因此在执行a的阶段弹出2。最后的3是因为在此函数被调用前对它进行了赋值操作,覆盖了前面的函数声明。

四. 函数解析

(这个地方我理解的也不是特别透彻,仅此拙见,望指正)

1)Execution context(执行上下文)

每个函数或者全局代码都会产生一个执行上下文,并在其中运行,而执行上下文的形式是一个object。其中包含

Execution context is an object which consists of:

  • variable object, which is activation object in case of functions
  • scope chain, which you can think of as a linked list of outer scopes
  • this value

2)变量对象

每个执行上下文都包含一个变量对象,这个变量对象是用来存储执行环境中的变量和函数声明,但不同的情况下,包含的数据不同。

Variable object is an abstract thing, which can be either one of those:

  • global object (in global context) - the place where global vars (like window, document or console in a browser) reside
  • activation object (for functions, which define scopes in ECMAScript)

函数表达式不包含在变量对象中

变量作用域&函数作用域

变量作用域&函数作用域

3)活动对象

当进入函数执行环境时,会产生一个活动对象(activation object)[在作用域链最前端的对象],包含了形参,arguments对象。它作为执行环境的变量对象,除了函数声明和变量名称还增加了形参和arguments对象。

Activation object is an object which holds:

  • formal args of the function
  • arguments object for this function
  • any vars and (named) functions inside this function

So, activation object is just a special case of variable object.

It is basically a container for all the local stuff you can access by name inside a function, except for this.变量作用域&函数作用域

针对于foo函数,它的活动对象包含下面的内容。

变量作用域&函数作用域

4)作用域链

在每个执行上下文中都会包含一个作用域链,用以存储函数作用域内的变量和函数声明和父级变量。当解析一个标识符(函数,形参,变量)的时候会从作用域链的变量对象开始查找,一级一级向上查找,类似于原型链的概念。

变量作用域&函数作用域

变量作用域&函数作用域

参考:http://dmitrysoshnikov.com/ecmascript/javascript-the-core/