I recently started a JavaScript coding bootcamp. Early on in the program we learned about scopes and variables, two very important foundational aspects of javascript. Both of which I took for granted immediately. “Yeah yeah… var, const, block-scoped… I get it!”
我最近开始了JavaScript编码训练营。 在程序的早期,我们学习了范围和变量,这是javascript的两个非常重要的基础方面。 我立即都认为这两者都是理所当然的。 “是的,是的... var,const,块作用域……我明白了!”
Now deep into the program I am spending hours: planning, writing out the code, and debugging; I go to work through one function, accessing one particular variable… and then… everything breaks. Blank. White. Screen. I open devTools to see a bright red banner and the words REFERENCE ERROR.
现在,我花了很多时间在程序上:计划,编写代码和调试; 我通过一个函数来工作,访问一个特定的变量……然后……一切都中断了。 空白。 白色。 屏幕。 我打开devTools看到鲜红色的横幅和单词REFERENCE ERROR。
Nothing feels more frustrating than a reference error! Save yourself from this fate and learn the different types of variables: how they are (or are not) hoisted, and what scopes you can access them in. It will save you sanity and heartbreak. I am telling you from experience!
没有什么比参考错误更令人沮丧的了! 从这种命运中解脱出来,并学习不同类型的变量:如何(或不)悬挂变量,以及可以在哪些范围内使用它们。这将节省您的理智和令人心碎的时间。 我是根据经验告诉你的!
If you are a retro video game nerd, let me help you understand the rules of scopes and variables with Nintendo’s Mario Universe:
如果您是复古电子游戏的书呆子,请让我帮助您了解任天堂的《马里奥宇宙》中范围和变量的规则:
When writing javascript, think of your code as sectioned off into scopes: global scope, local scope, block scope. Depending on what scope a variable is declared in and what type of variable is being used determines on where you can access that particular variable later on in the code.
在编写javascript时,请考虑将代码分为以下范围:全局范围,局部范围,块范围。 根据变量的声明范围和使用的变量类型,决定以后在代码中可以在何处访问该特定变量。
///全球范围/// (///GLOBAL SCOPE ///)
The global scope is the ultimate parent scope, I like to think of it as the omnipresent scope. It’s the largest scope and contains all other scopes inside of it. All of the other scopes are considered the global scope’s “children.” All of the global variables are always present, no matter the scope you just can’t see them until you called upon them: they are omnipresent.
全局范围是最终的父范围,我喜欢将其视为无所不在的范围。 它是最大的作用域,并且其中包含所有其他作用域。 所有其他范围都被视为全局范围的“子级”。 所有全局变量始终存在,无论您在调用它们之前都看不到它们的范围:它们无处不在。
- Think of the global scope as the Mario Universe in Nintendo. Global variables would include Mario, Luigi, Princess Peach, the Mushroom Kingdom, ect. Every game in Mario Universe can access these variables (even if every game does not use all of them all the time). 可以将全球范围视为任天堂的马里奥宇宙。 全局变量将包括Mario,Luigi,Peach Princess,Mushroom Kingdom等。 Mario Universe中的每个游戏都可以访问这些变量(即使每个游戏并非始终使用所有变量)。
///本地(或功能)范围/// (/// LOCAL (OR FUNCTION) SCOPE ///)
The local scope is a child to the global scope and is created when you make a function. All variables inside this local scope are accessible to the initial function the variable was created in and all children of that function. The global scope cannot access any variable in this scope unless that variable was first declared in the global scope.
局部作用域是全局作用域的子级,是在创建函数时创建的。 此局部作用域内的所有变量都可被创建该变量的初始函数及其所有子级访问。 全局范围不能访问该范围内的任何变量,除非该变量首先在全局范围内声明。
- In the scope for the marioKart() function the variable ‘vehicles’ is declared and initialized. ‘Vehicles’ is only accessible to this function or children of this function (ie MarioKart 64() or MarioKart Tour() ). The function of SmashBrothers() or SuperMarioBros() won’t be able to access the “ Bowser Bike” in vehicles variable. 在marioKart()函数的作用域中,声明和初始化变量“车辆”。 “车辆”仅可用于此功能或该功能的子功能(即MarioKart 64()或MarioKart Tour())。 SmashBrothers()或SuperMarioBros()的功能将无法访问车辆变量中的“ Bowser Bike”。
///区块范围/// (/// BLOCK SCOPE ///)
Block scope is very similar to local scope but instead of scoped to functions and nested functions the variables are scoped to a code block in if-statements and loops. Once again, all global variables can be accessed in a block scope but if you declare a variable with const or let inside the code block it is scoped to that block and all child blocks but not the global scope or any other block or function outside of itself.
块作用域与局部作用域非常相似,但是变量的作用域不是if语句和循环,而是作用域为代码块,而不是作用于函数和嵌套函数。 再一次,可以在块作用域中访问所有全局变量,但是如果您使用const声明变量或在代码块内部放置它,则该作用域将作用于该块和所有子块,但不能作用于全局作用域或该范围之外的任何其他块或函数本身。
Let’s say we are in a block scope for Yoshi’s Island. IF we are on Yoshi’s Island we can access the global Yoshi variable but there would also be a declared and initialize variable of YoshiSpecialAbilities and YoshiBackstory. Other games are block or function scoped and don’t have access to variables YoshiSpecialAbilities and YoshiBackstory. The global scope also doesn’t have access to those variables. Only ‘children scopes’ of the YoshisIsland has access to these YoshiSpecialAbilities (ie Yoshi’s Island 2 and Yoshi Island DS).
假设我们在Yoshi's Island的封锁范围内。 如果我们在Yoshi's Island上,则可以访问全局Yoshi变量,但是也会有一个YoshiSpecialAbilities和YoshiBackstory的声明和初始化变量。 其他游戏受块或函数限制,无法访问变量YoshiSpecialAbilities和YoshiBackstory。 全局范围也无法访问这些变量。 只有YoshisIsland的“儿童范围”才能使用这些YoshiSpecialAbilities(即Yoshi's Island 2和Yoshi Island DS)。
变量类型:VAR,LET和CONST (Variable Types: VAR, LET, and CONST)
Knowing your variable types goes hand-in-hand with using scope. The three types of variables are var, let, and const.
了解变量类型与使用范围密切相关。 变量的三种类型是var,let和const。
‘var’ is reassignable: at any point in your code you can reassign the value (if you aren’t careful you will change the value of an important variable). ‘var’ is hoisted so no matter where you declare it in your code the declaration of your variable will be hoisted to the top when it is read. ‘var’ is only function scoped not block-scoped. Meaning if you declare a variable with var in a function it will only be accessible to that function and the children of that function but if you declare it in a loop or if-statement it is not block-scoped, you will be able to access it outside that code block.
“ var”是可重新分配的:您可以在代码中的任何时候重新分配值(如果不小心,您将更改重要变量的值)。 悬挂'var',因此无论您在代码中的什么位置声明变量,在读取变量时,其声明都将悬挂在顶部。 'var'仅在作用域范围内而不是块作用域内。 意思是,如果在函数中用var声明变量,则该函数及其子函数只能访问该变量,但如果在循环或if语句中声明该变量,则该变量不受块作用域访问,则可以访问该变量它在该代码块之外。
- Mario would be great to assign with ‘var’ because he is constantly being reassigned and used in all scopes. However, use with caution: once you reassign the variable, the value has been completely changed for the rest of the code (unless you reassign it again): Mario最好用'var'进行分配,因为他会不断被重新分配并在所有范围内使用。 但是,请谨慎使用:重新分配变量后,其余代码中的值已完全更改(除非再次重新分配):
‘let’ is reassignable, so this variable has some flexibility if it needs to change. However all ‘let’ variables are function and block-scoped adding protection from accidentally reassigning the variable.
“ let”是可重新分配的,因此此变量在需要更改时具有一定的灵活性。 但是,所有“ let”变量都是函数和块作用域,从而增加了防止意外重新分配变量的保护。
- A ‘let’ variable for Mario Games are the environments. Every function or block scope for a particular game would have an environment variable that would change with each level but those variables are scoped only to that game. The environments are very specific and you would want to accidentally end up with the Mushroom Kingdom inside Luigi’s Mansion. Mario Games的“ let”变量就是环境。 特定游戏的每个功能或块作用域都将具有一个随每个级别而变化的环境变量,但这些变量仅作用于该游戏。 环境是非常特定的,您可能会意外地以路易吉大厦内的蘑菇王国告终。
‘const’ is not assignable, it is scoped to functions and block code, and it is not hoisted. This may sound very strict but it actually helps you make a lot less mistakes. ‘const’ variables are easy to keep track of and are definite, so you know exactly what you are dealing with at all times. Also since they are not hoisted they are only accessible after being declared and initialized.
'const'是不可分配的,它的作用域是功能和块代码,并且不被提升。 这听起来可能很严格,但实际上可以帮助您减少很多错误。 'const'变量易于跟踪并且是确定的,因此您始终可以确切地知道要处理的内容。 另外,由于未吊起它们,因此只有在声明和初始化之后才能访问它们。
- Captain Toad would be a great global const variable. She doesn’t appear in the universe until Mario Galaxy and doesn’t change. She is still accessible to block code and functions after a point but is not needed before (doesn’t need to be hoisted) and never needs to be reassigned. 蟾蜍队长将是一个伟大的全球const变量。 她直到Mario Galaxy才出现在宇宙中,并且不会改变。 在一个点之后,仍然可以访问她的代码和功能,但之前不需要(不需要将其吊起),也不需要重新分配它。
When in doubt: go with ‘const’. Then if it needs to be reassigned: go with ‘let’. If you still need more flexibility go with ‘var’. But if you start very strict it will leave less room for error down the line!
如有疑问,请使用“ const”。 然后,如果需要重新分配它,请使用“ let”。 如果您仍然需要更大的灵活性,请使用“ var”。 但是,如果您非常严格地进行操作,则将在一行中留下更少的错误空间!
This explanation sounds like fun and games but learning and understanding these fundamentals can really help save some debuggging time. Happy coding!
这种解释听起来很有趣,但实际上,学习和理解这些基础知识可以真正帮助节省调试时间。 编码愉快!
翻译自: https://medium.com/@meganeileenkosmoski/javascript-scopes-and-super-mario-76f51a1af56b