在javascript';创建阶段';?

在javascript';创建阶段';?,javascript,Javascript,我现在正在学习Udemy课程,我刚刚了解了解释器解释JS时发生的创建阶段和执行阶段 我有一个问题,但我将首先向您展示我正在使用的代码: 如果我理解正确,在创建阶段,变量和函数是“设置”的,这意味着它们在内存中被指定了点。变量都被赋予了未定义的占位符值。然后在执行阶段,引擎执行从顶部开始的行。当第一次调用b()时,“a”仍然具有未定义的占位符值,然后将“a”的初始值指定为“peas”,再次调用b(),这次“a”的值为“peas”。 在我看来,这里必须发生两件事中的一件。备选方案1:在创建阶段,所

我现在正在学习Udemy课程,我刚刚了解了解释器解释JS时发生的创建阶段和执行阶段

我有一个问题,但我将首先向您展示我正在使用的代码:

如果我理解正确,在创建阶段,变量和函数是“设置”的,这意味着它们在内存中被指定了点。变量都被赋予了未定义的占位符值。然后在执行阶段,引擎执行从顶部开始的行。当第一次调用b()时,“a”仍然具有未定义的占位符值,然后将“a”的初始值指定为“peas”,再次调用b(),这次“a”的值为“peas”。 在我看来,这里必须发生两件事中的一件。备选方案1:在创建阶段,所有变量都在函数之前设置。这意味着,当为函数b()创建内存空间时,该函数包含a的值undefined(因为已使用值undefined创建了“a”内存空间)。备选方案2:函数和变量按照它们所处的词法顺序设置(在本例中,b是在a之前创建的),当b被创建时,“a”引用以某种方式表示函数正在侦听任何可能创建的“a”内存位置,而当以后实际创建“a”位置时,参考系指的是那个地点


我在这两种情况下都正确吗?

你可以这样想。
您的原始代码:

b();

function b () {

  console.log(a);
}

var a = 'peas';

b();
实际上是这样执行的:

var a;
function b () {
  console.log(a);
}

b(); // log undefined because a doesn't have a value yet

a = 'peas';

b(); // log peas because a has a value
基本上,所有变量和函数定义都放在封闭范围的顶部。 顺序实际上并不重要,因为函数
b
中的代码在实际调用函数之前不会执行

如果我理解正确,在创建阶段,变量和函数是“设置”的,这意味着它们在内存中被指定了点

为此,我不会使用术语set——它通常用于指一个变量被设置(赋值)为一个特定的值。我也不会使用术语“斑点”或“记忆”——我们不需要担心这些内部问题。只需说声明就更清楚了

我也不太喜欢“创造阶段”这个词的使用,它既不标准又令人困惑——到底是什么在创造?我更喜欢“汇编”一词

变量都被赋予了未定义的占位符值

确切地说,我不会说它们“具有未定义的价值”,而是“没有价值”,或“未定义”<代码>未定义不是由尚未指定的变量所持有的值;相反,它是一个状态,当访问该状态时,该状态会导致变量计算为
未定义的值

备选方案1:在创建阶段,所有变量都在函数之前设置

是的,尽管再次使用“集合”这个词会让人困惑。比如,“所有变量在函数之前声明”。这是提升的过程

备选方案2:函数和变量按照它们所处的词法顺序设置(在本例中,b是在a之前创建的),当b被创建时,“a”引用以某种方式表示函数正在侦听任何可能创建的“a”内存位置,而当以后实际创建“a”位置时,参考系指的是那个地点

否。该函数不“侦听”任何内容。它只是在你告诉它的时候执行

这重要吗? 不是真的。它属于神秘的范畴。因此,我们用规则堵塞我们的大脑,比如变量以这种方式提升,函数声明以其他方式提升,
let
还有其他提升行为。实际上,几乎所有的样式指南都会要求您在函数顶部声明变量,如果您不这样做(或者可以配置为这样做),linter会警告您。这立即消除了所有可变吊装问题

有些人喜欢将内部函数放在函数的底部,这很好,因为如果它是一个函数声明(即
function foo(){}
),那么整个过程(包括定义)都会被提升。如果它是一个函数表达式被赋值给一个变量(即
var foo=function(){}
),那么它就是一个变量,我们已经决定把它放在函数的顶部——参见上面的段落

一般来说,如果您的程序依赖于提升行为,那么它编写得很糟糕。如果您需要了解提升行为以了解程序的工作方式,那么它的编写就很糟糕

总之,您真正需要学习的只有一条规则:将变量声明(及其初始化)放在函数的顶部。那你就不必担心起重了

(也有一些例外情况,例如在
for
语句中声明变量,如
for(var i..)
,假设
i
不用于循环索引以外的任何内容,这很好。)


出于某种原因,学习JS的人有时似乎会关注这些奇怪的事情——比如“为什么
”“==假
或其他什么。我建议你把重点放在如何思考你的问题上,并把它们分解开来,然后编写一个干净的代码,这样你和其他人就可以不用担心这个奥秘而维护它了。我写JS已经很多年了,不记得上次遇到提升相关问题是什么时候了。

我不确定实现的细节,但一个好的经验法则是,在
var
语句中,变量的声明被提升,但赋值部分没有。所以你的选择2是错误的。关于备选方案1,我认为所有变量和函数都分配了内存
var a;
function b () {
  console.log(a);
}

b(); // log undefined because a doesn't have a value yet

a = 'peas';

b(); // log peas because a has a value