简体   繁体   English

LET 与 VAR 以及从块范围到全局范围的提升

[英]LET vs VAR and Hoisting from Block Scope to Global Scope

In light of questions:根据问题:

Understanding let vs. var hoisting and 理解 let 与 var 提升

Are variables declared with let or const not hoisted in ES6? ES6 中是否未提升使用 let 或 const 声明的变量?

I do not understand what happens when hoisting lifts a variable out of block scope, into global scope.我不明白当提升将变量从块范围提升到全局范围时会发生什么。

In my code, I have:在我的代码中,我有:

<script>

    "use strict";

    let PageInit = null;

    document.addEventListener("DOMContentLoaded", () => {

        PageInit = new IPageInit();

        doSomething();

    });

    function doSomething() {
        alert(PageInit.RefreshCounter); // 60 //correct
    }

</script>

PageInit being created in the global scope is visible to doSomething() .在全局范围内创建的PageInitdoSomething()可见。

However, if I do this:但是,如果我这样做:

<script>

    "use strict";

    document.addEventListener("DOMContentLoaded", () => {

        var PageInit = new IPageInit();

        doSomething();

    });

    function doSomething() {
        alert(PageInit.RefreshCounter); // referenceError
    }

</script>

I am not understanding hoisting properly.我不理解正确吊装。 I expected that var PageInit inside block scope would get hoisted into global scope, first thing inside the <script> tag.我希望块作用域内的var PageInit会被提升到全局作用域中,首先是<script>标记内的东西。

But it doesn't.但事实并非如此。

Can anyone explain why not?谁能解释为什么不呢? Or where does it get hoisted to?或者它被吊到哪里?

document.addEventListener("DOMContentLoaded", () => {

    var PageInit = new IPageInit();

    doSomething();

});

var has a functional scope. var有一个功能范围。 This means no matter where you declare a variable in a function, it's available to the entire function.这意味着无论您在函数中的何处声明变量,它都可用于整个函数。

 function fn () { console.log(b) var b = 10 } fn() /* this is same as writing function fn () { var b ======================> hoisted console.log(b) b = 10 } */

This doesn't mean that the variable declared inside a function would be available outside of it.这并不意味着在函数内部声明的变量在函数外部可用。 And this is why PageInit in doSomething function gives reference error.这就是为什么doSomething函数中的PageInit给出引用错误的原因。 You will have to initialize the variable outside the function to not get this error您必须在函数外部初始化变量才能不会出现此错误

Scope in JavaScript JavaScript 中的作用域

Scope in JavaScript defines accessibility of variables, objects and functions. JavaScript 中的作用域定义了变量、对象和函数的可访问性。

There are two types of scope in JavaScript. JavaScript 中有两种作用域。

  1. Global Scope全球范围
  2. Local Scope本地范围

Global Scope全球范围

Variables declared outside of any function become global variables.在任何函数之外声明的变量成为全局变量。 Global variables can be accessed and modified from any function.可以从任何函数访问和修改全局变量。

Local Scope本地范围

Variables declared inside any function with var keyword are called local variables.在任何带有 var 关键字的函数中声明的变量称为局部变量。 Local variables cannot be accessed or modified outside the function declaration.不能在函数声明之外访问或修改局部变量。

We all know that let is block scope and var is it's current execution context .我们都知道let是块作用域, var是它的当前执行上下文。

Conclusion结论

In your first example let can be access because it's scope is global and he is in main block.在您的第一个示例中, let可以访问,因为它的范围是全局的,并且他在主块中。 In your second example var is in it's local scope that's why it is unable to output it's value在你的第二个例子中, var在它的本地范围内,这就是为什么它无法输出它的值

I'm having trouble figuring out what your intention is in the script.我无法弄清楚您在脚本中的意图。 however and in any case ....然而,无论如何......

no, var is valid within its " general purpose scope " so " in the tree of its functions and subfunctions ".不, var在其“通用范围”内有效,因此“在其功能和子功能树中”。 So you don't find it because you are instancing a new situation and that var will be lost if not passed between the parameters.所以你找不到它,因为你正在实例化一个新的情况,如果没有在参数之间传递 var 将会丢失。

If you use let it is even worse because it is valid only within that function and does not access the sub functions if not passed as a parameter.如果使用let则更糟,因为它仅在该函数内有效,并且如果不作为参数传递则不会访问子函数。

In all this you are acting on an event system ... events are simil to ajax (create only on moment and lost out that event).在所有这些中,您正在对事件系统进行操作……事件类似于 ajax(仅在瞬间创建并丢失该事件)。 it's difficult to process them by extracting data without saving them somewhere or pass it from function to another.很难通过提取数据而不将它们保存在某处或将其从函数传递给另一个函数来处理它们。

it is useful for understanding: https://dev.to/sarah_chima/var-let-and-const--whats-the-difference-69e它有助于理解: https : //dev.to/sarah_chima/var-let-and-const--whats-the-difference-69e

a more correct version would be like:更正确的版本是这样的:

simple idea (I have not tested it but the logic is that)简单的想法(我没有测试过,但逻辑是这样)

var XXX;

document.addEventListener("DOMContentLoaded", XXX => {

    XXX = new IPageInit();

    doSomething(XXX);

}, false); 

function doSomething(myval) {
    alert(myval); // now have XXX here 
}

So... xxx passed into success of event => and passed on doSomethig.所以... xxx 传递到成功的事件 => 并传递了 doSomethig。

or...或者...

document.addEventListener("DOMContentLoaded", () => {

    var XXX = getaval();

    doSomething(XXX);

}, false); 

function getaval() {
     return IPageInit(); // now have XXX here 
}

function doSomething(myval) {
    alert(myval); // now have XXX here 
}

So... on event => get or do what you have.所以......在事件=>得到或做你所拥有的。 if have nothing... get.如果什么都没有……得到。

I hope I have been useful to you at least a little.我希望我至少对你有用。

I do not understand what happens when hoisting lifts a variable out of block scope, into global scope.我不明白当提升将变量从块范围提升到全局范围时会发生什么。

This never happens.这永远不会发生。

Hosting affects when a variable comes into existence, not where .托管影响变量何时存在,而不是where

 document.addEventListener("DOMContentLoaded", () => { PageInit = new IPageInit();

That implicitly declares a global.这隐含地声明了一个全局变量。 It isn't hosted.它不是托管的。 The variable doesn't exist until the function is run.在函数运行之前,变量不存在。 Trying to read the variable before then will result in an exception.在此之前尝试读取变量将导致异常。

 document.addEventListener("DOMContentLoaded", () => { var PageInit = new IPageInit();

var declares a variable in the scope of the function it is declared inside. var在其内部声明的函数范围内声明了一个变量。 So it won't create a global.所以它不会创建一个全局。

It is hoisted … but as it is the first line in the function, that makes no practical difference.提升了……但因为它是函数中的第一行,所以没有实际区别。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM