Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

变量对象(真正理解何为提升) #7

Open
amandakelake opened this issue Feb 7, 2018 · 1 comment
Open

变量对象(真正理解何为提升) #7

amandakelake opened this issue Feb 7, 2018 · 1 comment

Comments

@amandakelake
Copy link
Owner

amandakelake commented Feb 7, 2018

变量对象(理解提升很有作用)

#前端/Javascript/个人理解总结

执行上下文

当前栈顶的执行上下文包括了:变量对象、作用域链、this
image

执行上下文的生命周期

当一个函数被激活时,一个新的执行上下文就会被创建(这个执行上下文在栈顶),一个执行上下文的生命周期分为两个阶段
1、创建阶段:在这个阶段中,执行上下文会分别创建变量对象,建立作用域链,以及确定this的指向
2、代码执行阶段: 变量赋值,函数引用、以及执行其他代码
image

创建变量对象VO:Variable Object
  • 1、建立arguments对象
    当前上下文中的参数,建立该对象下的属性与属性值
  • 2、检查当前上下文的函数声明(这就是为什么函数是一等公民)
    使用function关键字声明的函数。在变量对象中以函数名建立一个属性,属性值为指向该函数所在内存地址的引用。如果函数名的属性已经存在,那么该属性将会被新的引用所覆盖。
    这里要清楚理解,函数声明才会被提升,函数表达式不会被提升,函数表达式就相当于变量声明
  • 3、检查当前上下文中的变量声明
    每找到一个变量声明,就在变量对象中以变量名建立一个属性,属性值为undefined。如果该变量名的属性已经存在,为了防止同名的函数被修改为undefined,则会直接跳过,原属性值不会被修改。
    也就是同一个执行上下文中,变量对象是唯一的,但有可能在下个阶段(代码执行阶段)被修改赋值
创建阶段(注意函数的引用覆盖、变量的跳过)
VO = {
  arguments: {...},
  foo: <foo reference>, //这个地方,优先函数声明,碰到变量foo不会被覆盖,因为var声明的变量当遇到同名的属性时,会跳过而不会覆盖
  bar: underfined //虽然bar是函数表达式,但也只当做变量来处理
}
执行阶段(变量对象 => 活动对象,赋值和引用,碰到相同的属性名会无条件覆盖)
VO => AO 
VO = {
  arguments: {...},
  foo: 'Hello', //要理解这里为什么是变量,而不再是函数了,因为在执行阶段会按顺序进行赋值或者引用
  bar: <bar reference>,
  this: Window
}

预编辑

function test() {
	//创建变量对象阶段
  var foo; 
  //一等公民函数,优先声明,并指向函数的引用地址
  // foo => function foo() {
  //   return 'hello';
  // }
  var bar : underfined

	// 代码执行阶段:变量赋值,函数引用, 全部按照顺序来
	console.log(foo); //函数引用
	console.log(bar); // underfined
	// 这里按顺序执行到这里,重新给变量foo赋值
	foo = 'Hello';
	console.log(foo); // 'Hello'
	bar = function () {
    return 'world';
  }
}

再看一个例子

function testOrder(arg) {
    console.log(arg); // arg是形参,不会被重新定义
    console.log(a); // 因为函数声明比变量声明优先级高,所以这里a是函数
    var arg = 'hello'; // var arg;变量声明被忽略, arg = 'hello'被执行
    var a = 10; // var a;被忽视; a = 10被执行,a变成number
    function a() {
        console.log('fun');
    } // 被提升到作用域顶部
    console.log(a); // 输出10
    console.log(arg); // 输出hello
}; 
testOrder('hi');

输出

hi 
function a() {
        console.log('fun');
    }
10 
hello 
@zhangenming
Copy link

变量对象VO就是当前作用域
作用域链也是VO链

可否这样理解

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants