在执行上下文方面,为什么JavaScript中会出现变量提升
我知道变量提升是因为执行上下文中的一些步骤。在执行上下文方面,为什么JavaScript中会出现变量提升,javascript,Javascript,我知道变量提升是因为执行上下文中的一些步骤。 那么,为什么在JavaScript中会出现执行上下文方面的变量提升呢 找到一些代码来调用函数 在执行函数代码之前,创建执行上下文。 初始化范围链 创建变量对象: 创建arguments对象,检查参数的上下文,初始化名称和值,并创建引用副本 扫描上下文中的函数声明: 对于找到的每个函数,在变量对象中创建一个属性,该属性是确切的函数名,它有一个指向内存中函数的引用指针 如果函数名已经存在,则引用指针值将被覆盖 对于找到的每个变量声明,在变量对象中创建一个
那么,为什么在JavaScript中会出现执行上下文方面的变量提升呢 找到一些代码来调用函数 在执行函数代码之前,创建执行上下文。 初始化范围链 创建变量对象: 创建arguments对象,检查参数的上下文,初始化名称和值,并创建引用副本 扫描上下文中的函数声明: 对于找到的每个函数,在变量对象中创建一个属性,该属性是确切的函数名,它有一个指向内存中函数的引用指针 如果函数名已经存在,则引用指针值将被覆盖 对于找到的每个变量声明,在变量对象中创建一个属性作为变量名,并将值初始化为未定义 如果变量名已存在于变量对象中,则不执行任何操作并继续扫描 确定上下文中“this”的值 在上下文中运行/解释函数代码,并在代码逐行执行时分配变量值 让我们看一个例子:
function foo(i) {
var a = 'hello';
var b = function privateB() {
};
function c() {
}
}
foo(22);
On calling foo(22), the creation stage looks as follows:
fooExecutionContext = {
scopeChain: { ... },
variableObject: {
arguments: {
0: 22,
length: 1
},
i: 22,
c: pointer to function c()
a: undefined,
b: undefined
},
this: { ... }
}
如您所见,创建阶段处理定义属性的名称,而不是为属性赋值,形式参数/参数除外
创建阶段完成后,执行流进入函数,函数完成执行后,激活/代码执行阶段如下所示:
fooExecutionContext = {
scopeChain: { ... },
variableObject: {
arguments: {
0: 22,
length: 1
},
i: 22,
c: pointer to function c()
a: 'hello',
b: pointer to function privateB()
},
this: { ... }
}
一句关于提升的话
您可以在网上找到许多在JavaScript中定义术语提升的资源,解释变量和函数声明被提升到其函数范围的顶部。但是,没有人能详细解释为什么会发生这种情况,并且有了关于解释器如何创建激活对象的新知识,很容易理解为什么会发生这种情况。以下面的代码示例为例:
(function() {
console.log(typeof foo); // function pointer
console.log(typeof bar); // undefined
var foo = 'hello',
bar = function() {
return 'world';
};
function foo() {
return 'hello';
}
}());
我们现在可以回答的问题是:
为什么我们可以在声明foo之前访问它?
如果我们遵循创建阶段,我们知道在激活/代码执行阶段之前已经创建了变量。因此,当函数流开始执行时,已经在激活对象中定义了foo。
Foo声明了两次,为什么Foo显示为函数而不是未定义或字符串
尽管foo声明了两次,但我们从创建阶段就知道,函数是在变量之前在激活对象上创建的,如果属性名称已经存在于激活对象上,我们只需绕过减速
因此,首先在激活对象上创建对函数foo()的引用,当我们获取解释器并获取var foo时,我们已经看到属性名foo存在,因此代码不做任何操作并继续。
为什么酒吧没有定义
bar实际上是一个具有函数赋值的变量,我们知道这些变量是在创建阶段创建的,但它们是用未定义的值初始化的
这是语法的一部分,这就是它如何工作的原因。是的,这就是Javascript设计的方式。。或者你可以问Brendan.虽然这个问题是有效的(据我所知),但几乎只有JavaScript的创建者Brendan Eich才能回答这个问题。或者是从事语言规范工作的人。但我不相信它们经常出现堆栈溢出。如果你只是问它是如何工作的,那是另一个故事。你应该更清楚地说明,整个答案都是复制粘贴而来的。我认为这是他问的问题的完整解决方案,所以我做了这个,但如果你这么说,我会做的。谢谢。我认为@Akhilesh是对的。