function test() { console.log(a); // undefined console.log(foo()); // 2 var a = 1; function foo() { return 2; }; }; test();
不是很准确的草图,大概了解就好。数组
建立阶段:
在这个阶段中,执行上下文分别会建立变量对象、创建做用域链,以及肯定this的指向。浏览器
代码执行阶段:
建立完成后,就会开始执行代码,这个时候,会完成变量赋值,函数引用,以及执行其余代码。函数
变量对象的建立,经历如下过程。测试
创建arguments对象。检查上下文中的参数,创建该对象下的属性与属性值(key-value)this
检查当前上下文的函数声明,也就是使用function关键字声明的函数。在变量对象中以函数名创建一个属性,属性值为指向该函数所在内存地址的引用。若是函数名的属性已经存在,那么该属性将会被新的引用所覆盖。spa
检查当前上下文中的变量声明,每找到一个变量声明,就在变量对象中以变量名创建一个属性,属性值为undefined。若是该变量名的属性已经存在,为了防止同名的函数被修改成undefined,则会直接跳过,原属性值不会被修改。指针
因此,因而就有了图中的VO引用的对象的图示,这就是变量提高的真正缘由,对于函数声明,它的优先级是大于变量声明的,因此在建立阶段,函数声明的函数名就持有了函数的引用。而变量赋值须要在后面的执行阶段才被赋值。code
未进入执行阶段前,变量对象中的属性都不能被访问!可是进入执行阶段以后,变量对象转变为了活动对象(Active Object),里面的属性都能被访问了,而后开始进行执行阶段的操做。对象
目前个人测试:blog
函数内设有形参,可是不传实参,遍历arguments对象时没有任何值
函数内不设形参,可是传实参,遍历arguments对象有值对应的索引
function test(a,b,c,d) { for (var i in arguments) { console.log(i); } console.log(arguments.length+"个"); }; test(1,2,3,4); // 0 1 2 3 // "4个" function test2(a,b,c,d) { for (var i in arguments) { document.write(i+"<br />") } document.write(arguments.length+"个"); }; test2(); // 什么也没有 // 0个
脑子里有这副图后,咱们在来看另外一个栗子:
function test() { console.log(foo()); console.log(bar); var foo = "Hello"; console.log(foo); var bar = function () { return "world"; }; function foo() { return "hello"; }; }; test(); // "hello" // "undefined" // "Hello"
主要讨论同变量声明与同变量声明与函数声明的状况,这也是变量对象在建立时所作的工做;
检查当前上下文的函数声明,也就是使用
function
关键字声明的函数。在变量对象中以函数名创建一个属性,属性值为指向该函数所在内存地址的引用。若是函数名的属性已经存在,那么该属性将会被新的引用所覆盖。检查当前上下文中的变量声明,每找到一个变量声明,就在变量对象中以变量名创建一个属性,属性值为
undefined
。若是该变量名的属性已经存在,为了防止同名的函数被修改成undefined
,则会直接跳过,原属性值不会被修改。
如代码中的foo
,在test
函数的执行上下文建立变量对象后,建立阶段,foo
就是变量对象中的的键名(Key),而键值就是函数的地址指针,由于函数声明的优先级大于变量声明,因此foo
此时就持有了函数的引用,而var foo
的变量声明就被跳过。
执行阶段,进行赋值操做,foo
被从新赋值"Hello"
,同时变量bar
从未赋值(undefined
)到持有一个函数的引用,这就是变量对象=>活动对象,执行栈,执行上下文所发生的操做。
var globla = 10; function test() { return globla++; }; test();
// 以浏览器中为例,全局对象为window // 全局上下文 windowEC = { VO: window, scopeChain: {}, this: window }
以浏览器中为例,全局对象为window
。
全局上下文有一个特殊的地方,它的变量对象,就是window
对象。而这个特殊,在this
指向上也一样适用,this
也是指向window
。除此以外,全局上下文的生命周期,与程序的生命周期一致,只要程序运行不结束,好比关掉浏览器窗口,全局上下文就会一直存在。其余全部的上下文环境,都能直接访问全局上下文的属性。