JS提升如何与块语句一起使用?

时间:2018-05-06 10:02:21

标签: javascript scope hoisting

在下面的snipet中,我只是想了解为什么console.log(abc in this);打印为true,但在下一行console.log(abc);获取undefined

console.log(this.abc);//undefined
console.log(abc in this);//true
console.log(abc);//undefined
{
    function abc(){
        console.log("hello");
    }
}
console.log(abc); //ƒ abc(){console.log("hello");

你们中的任何人都可以解释在这种情况下Hoisting和Block语句是如何工作的吗?

3 个答案:

答案 0 :(得分:2)

在草率模式下,this指的是全局对象。像这样的普通非函数块中的函数将其变量名提升到外部作用域,但实际函数不会被赋值给外部变量(到窗口属性)直到内部块被执行。

详情请见此处:

What are the precise semantics of block-level functions in ES6?

正如其他问题所解释的那样,对于解释器,您的代码看起来像这样:

window.abc = undefined; // top-level hoisting assigns to window properties
console.log(window.abc); // undefined
console.log(window.abc in window); // true
console.log(window.abc); // undefined
{
  var _abc = function abc() {
    console.log("hello");
  };
  window.abc = _abc;
}
console.log(window.abc); //ƒ abc(){console.log("hello");

abc in this为真的原因是因为abc 已将初始化为窗口对象的属性,但尚未为其分配值。它与此处发生的情况类似:

const obj = { foo: undefined };
console.log('foo' in obj);

答案 1 :(得分:1)

简单地说,使用console.log(abc in this);检查它是否存在,因此记录true,但是您无法访问它,因此获取undefined两个console.log在函数声明之前执行。

答案 2 :(得分:-1)

如果您想知道为什么会发生这种情况,答案很简单,提升将所有声明移到他的范围顶部,所以:

console.log(this.abc); //undefined
console.log(abc in this); //true
console.log(abc); //undefined

function abc() {
  console.log("hello");
}

console.log(abc); //ƒ abc(){console.log("hello");

所以在内部函数中,函数abc()被声明在当前作用域的顶部,几乎保持在同一位置,但只是声明,因此当你尝试访问时,声明了var abc然后被赋值。他已经知道了这个函数,在你得到未定义的第一个console.log中

console.log(abc)函数_abc尚未进行十分转换,但在第二个示例中,您可以访问它,因为它访问了windows对象并获取了abc。

所以简而言之,javascript首先初始化变量,因为在第二个console.log中已经声明了所有变量并且它们在window对象中声明,访问abc就可以了。