有人会帮忙解释为什么下面的两段代码会打印出不同的结果吗?
区别在于条件语句。首先,有一个本地变量分配' Jack'要命名,条件是真实的(意思是!名称评估为真)。在第二个,同名的杰克'被分配但是全局变量名称,但条件是假的(!name是false)。我的问题是,如果所有其他条件相同,为什么第一个条件为真,第二个条件为假,如果改变的是 in 条件体?
我唯一的解释是条件的主体由JS解释器首先读取,这就是它如何确定name
是全局/本地的,变量声明是否需要是否悬挂,最后记录不同的名称值。
在开始解释它的正文之前,是否应首先评估条件布尔值?然后在这两种情况下,变量名称'将被评估为' undefined' ...任何帮助将不胜感激!
关于提升/范围上下文有一些非常好的资源,但我没有找到专门回答这个问题的资源。
http://javascriptissexy.com/javascript-variable-scope-and-hoisting-explained/
var name = "Paul";
function users () {
if (!name) {
var name = "Jack"; //<== difference is here, *inside* conditional body
}
console.log(name);
}
users(); //outputs "Jack"
VS。
var name = "Paul";
function users () {
if (!name) {
name = "Jack"; //<== difference is here, *inside* conditional body
}
console.log(name);
}
users(); //outputs "Paul"
答案 0 :(得分:5)
变量声明提升到执行上下文的顶部,在本例中是函数用户。重写这些以显示它从提升的角度看起来往往会消除任何混乱
var name = "Paul";
function users () {
var name;//<- hoisted variable declaration
if (!name) {
name = "Jack";
}
console.log(name);
}
users(); //outputs "Jack"
VS。
var name = "Paul";
function users () {
if (!name) {//no hoisted variable declaration, uses global
name = "Jack";
}
console.log(name);
}
users(); //outputs "Paul"
执行上下文包含几个关键组件,这里最相关的是词法环境和可变环境。如果您对此感兴趣,我会更深入地介绍两者之间的差异(以及一些简短的历史记录):https://stackoverflow.com/a/32573386/1026459
答案 1 :(得分:2)
使用var
时,您要在当前范围内实例化变量。 - 在第一种情况下,是user
函数的范围。
当您不使用var
时,您只是在该范围内没有该变量(function
)。既然您已经在当前范围(name
)之外实例化了变量globally
,那么您可以将其作为变量name
var name = "Paul";
function users () {
// var name; is essentially hoisted to here - the top of the current scope
if (!name) {
(var) name = "Jack"; // that hoisted var is set here
}
console.log(name);
}
users(); //outputs "Jack"
其他情况:
var name = "Paul";
function users () {
if (!name) {
name = "Jack"; // name is hoisted outside of the scope,
// but it already is declared as "Paul"
}
console.log(name);
}
users(); //outputs "Paul"
答案 2 :(得分:-1)
这是订单!
优先顺序。在解析时的文档代码中,在代码开始执行之前对函数进行求值。但是声明的变量在任何给定的上下文中都有更高的优先级。并且只有在实例化所有变量之后才允许函数运行。
这就是具有声明变量“name”的函数返回其本地名称的值的原因。因为它已经存在并且函数不必在外部范围内“查找”它的值。
修改
为了更深入的理解,这里有一个更有趣的例子:
var name = "Paul";
function users () {
name = "Dietrich";
if (!name) {
var name = "Jack";
}
console.log(name);
}
users(); // outputs "Dietrich"
console.log(name); // again outputs "Paul"
刚刚发生了什么?
声明name = "Dietrich"
是否应该定位到全局'name'变量值?
为什么这个功能在返回“Jack”时不会像以前那样持续存在?或者 - 为什么输出突然不是“杰克”,当然不是“保罗”了,而是奇怪的,完全出乎意料的“迪特里希”?!
- 正是出于同样的原因,它坚持重新调整“杰克”,而不是遵循函数语义及其条件暗示预期,并且那就是“保罗”。
这是出于上述原因。在第一眼和功能宣言中我们name = "Dietrich"
明确针对全球“保罗”
比,我们还有一个额外的预防措施,一个条件,它应该阻止执行“杰克”,因为外部范围已经有一个变量“名称”。但无济于事......
然而让事情变得更加混乱 - 全球“保罗”仍然完好无损!
Wee仅从我们的阅读点将“Dietrich”指定为来自外部范围的“name”变量。因为var(s)在函数之前和函数体声明开始执行之前很久就会得到评估。
从if(condition){ doesn't create a scope of its own }
开始,我们声明'name'变量并不重要。现在每个方程都已解决。
name = "Dietrich"
将不再修改外部作用域的全局“名称”,因为“name”变量已存在于此(本地)函数作用域中,因此通常“Dietrich”会覆盖本地“Jack”不是宇宙的搭便车“保罗”。那是因为var name
已经在当前范围的某处定义了。
因此,它之前用于返回“意外”“杰克”的原因相同。就这样。