在sec. 10.3中描述了执行上下文的组件,如下所示:
一个的LexicalEnvironment和VariableEnvironment组件 执行上下文始终是Lexical Environments。执行时 上下文创建了它的LexicalEnvironment和VariableEnvironment 组件最初具有相同的值。的价值 VariableEnvironment组件永远不会更改 在执行代码期间,LexicalEnvironment组件可能会更改 在执行环境中。
好的,我们有代码片段:
{
alert(o.prop);
var o={prop: 'prop'};
}
当控件转移到此代码段时,将创建相应的执行上下文并将其推送到堆栈。此上下文将成为正在运行的执行上下文(称为cont
)。在cont
创建VariableEnvironment
正在创建cont
期间。在cont
创建后,此代码开始执行。
但如sec.10.3
所述VariableEnvironment组件的值永远不会改变
因此,我们可以假设在VariableEnvironment
创建后cont
从未改变过。即cont
VariableEnvironment
的环境记录包含VariableStatement
和FunctionDeclarartion
最初创建的所有绑定。因此,我们可以通过引用o
来应用于对象。但我有TypeError: o is undefined
。
问题:
为什么导致上述TypeError
?我期望prop
将显示警告消息,因为the value of the VariableEnvironment component never changes
因此VariableEnvironment
的环境记录永远不会更改,因此此记录的所有绑定都是不可变的。
我可能不理解value of EnvironmentRecord
的正确意思吗?
答案 0 :(得分:4)
首先,您的代码只是定义块,而JavaScript没有块范围;环境记录与全局范围和功能相关联,而不是块。
因此,我们假设它实际上是一个函数,因此它创建了一个新的范围和环境记录:
function foo()
{
alert(o.prop);
var o={prop: 'prop'};
}
这被视为完全如此:
function foo()
{
var o;
o = undefined;
alert(o.prop);
o={prop: 'prop'};
}
哪一点应该澄清一下。 :-)你试图解除引用o
,好像它引用了一个对象,但它没有(还);它的值是undefined
。
这是因为在进入执行上下文后处理所有var
声明,并且在完成任何逐步工作之前,所有变量都初始化为undefined
。与var
相关联的任何初始化程序(例如,var o = ...
)实际上是一个赋值,并且在逐步执行代码时到达该代码时发生
更多(在我的博客上):