Scope defines the lifetime and visibility of a variable. Variables are not visible outside the scope in which they are declared.
范围定义变量的生存期和可见性。 变量在声明范围之外不可见。
JavaScript has module scope, function scope, block scope, lexical scope and global scope.
JavaScript具有模块范围,函数范围,块范围,词法范围和全局范围。
全球范围 (Global Scope)
Variables defined outside any function, block, or module scope have global scope. Variables in global scope can be accessed from everywhere in the application.
在任何函数,块或模块范围之外定义的变量具有全局范围。 可以从应用程序中的任何位置访问全局范围内的变量。
When a module system is enabled it’s harder to make global variables, but one can still do it. By defining a variable in HTML, outside any function, a global variable can be created:
启用模块系统后,很难创建全局变量,但是仍然可以做到。 通过在HTML中定义任何函数之外的变量,可以创建全局变量:
<script>
let GLOBAL_DATA = { value : 1};
</script>
console.log(GLOBAL_DATA);
When there is no module system in place, it is a lot easier to create global variables. A variable declared outside any function, in any file, is a global variable.
如果没有适当的模块系统,则创建全局变量要容易得多。 在任何文件中的任何函数外部声明的变量是全局变量。
Global variables are available for the lifetime of the application.
全局变量在应用程序的生存期内可用。
Another way for creating a global variable is to use the window global object anywhere in the application:
创建全局变量的另一种方法是在应用程序中的任何位置使用window全局对象:
window.GLOBAL_DATA = { value: 1 };
At this point, the GLOBAL_DATA variable is visible everywhere.
此时, GLOBAL_DATA变量随处可见。
console.log(GLOBAL_DATA)
As you can imagine these practices are bad practices.
您可以想象这些做法是不良做法。
模块范围 (Module scope)
Before modules, a variable declared outside any function was a global variable. In modules, a variable declared outside any function is hidden and not available to other modules unless it is explicitly exported.
在模块之前,在任何函数外部声明的变量是全局变量。 在模块中,在任何函数外部声明的变量都是隐藏的,除非明确导出,否则其他模块无法使用。
Exporting makes a function or object available to other modules. In the next example, I export a function from the sequence.js module file:
导出使功能或对象可用于其他模块。 在下一个示例中,我从sequence.js模块文件中导出一个函数:
// in sequence.js
export { sequence, toList, take };
Importing makes a function or object, from other modules, available to the current module.
导入使其他模块的功能或对象可用于当前模块。
import { sequence, toList, toList } from "./sequence";
In a way, we can imagine a module as a self-executing function that takes the import data as inputs and returns the export data.
从某种意义上说,我们可以将模块想象为一个自执行功能,该模块将导入数据作为输入并返回导出数据。
功能范围 (Function Scope)
Function scope means that parameters and variables defined in a function are visible everywhere within the function, but are not visible outside of the function.
函数范围是指函数中定义的参数和变量在函数内的任何位置都是可见的,但在函数外则不可见。
Consider the next function that auto-executes, called IIFE.
考虑下一个自动执行的功能,称为IIFE。
(function autoexecute() {
let x = 1;
})();
console.log(x);
//Uncaught ReferenceError: x is not defined
IIFE stands for Immediately Invoked Function Expression and is a function that runs immediately after its definition.
IIFE代表立即调用函数表达式,并且是在定义后立即运行的函数。
Variables declared with var have only function scope. Even more, variables declared with var are hoisted to the top of their scope. This way they can be accessed before being declared. Take a look at the code below:
用var声明的变量仅具有函数作用域。 更甚者,用var声明的变量被提升到其作用域的顶部。 这样,可以在声明它们之前对其进行访问。 看下面的代码:
function doSomething(){
console.log(x);
var x = 1;
}
doSomething(); //undefined
This does not happen for let. A variable declared with let can be accessed only after its definition.
这不会let发生。 用let声明的变量只能在定义后才能访问。
function doSomething(){
console.log(x);
let x = 1;
}
doSomething();
//Uncaught ReferenceError: x is not defined
A variable declared with var can be re-declared multiple times in the same scope. The following code is just fine:
使用var声明的变量可以在同一范围内多次重新声明。 下面的代码就可以了:
function doSomething(){
var x = 1
var x = 2;
console.log(x);
}
doSomething();
Variables declared with let or const cannot be re-declared in the same scope:
用let或const声明的变量不能在同一范围内重新声明:
function doSomething(){
let x = 1
let x = 2;
}
//Uncaught SyntaxError: Identifier 'x' has already been declared
Maybe we don’t even have to care about this, as var has started to become obsolete.
也许我们甚至不必在乎这个,因为var已经开始过时了。
区块范围 (Block Scope)
Block scope is defined with curly braces. It is separated by { and }.
块范围用花括号定义。 它由{和}分隔。
Variables declared with let and const can have block scope. They can only be accessed in the block in which they are defined.
用let和const声明的变量可以具有块作用域。 只能在定义它们的块中访问它们。
Consider the next code that emphasizes let block scope:
考虑下一个强调let块作用域的代码:
let x = 1;
{
let x = 2;
}
console.log(x); //1
In contrast, the var declaration has no block scope:
相反, var声明没有块作用域:
var x = 1;
{
var x = 2;
}
console.log(x); //2
Another common problem with not having block scope is the use of an asynchronous operation like setTimeout() in a loop. The flowing loop code displays the number 5, five times.
没有块作用域的另一个常见问题是在循环中使用诸如setTimeout()类的异步操作。 循环代码显示数字5,五次。
(function run(){
for(var i=0; i<5; i++){
setTimeout(function logValue(){
console.log(i); //5
}, 100);
}
})();
The for loop statement, with the let declaration, creates a new variable locale to the block scope, for each iteration. The next loop code shows 0 1 2 3 4 5.
带有let声明的for循环语句为每次迭代创建一个到块作用域的新变量语言环境。 下一个循环代码显示0 1 2 3 4 5 。
(function run(){
for(let i=0; i<5; i++){
setTimeout(function log(){
console.log(i); //0 1 2 3 4
}, 100);
}
})();
词汇范围 (Lexical Scope)
Lexical scope is the ability of the inner function to access the outer scope in which it is defined.
词法范围是内部函数访问定义它的外部范围的能力。
考虑下一个代码 :
(function autorun(){
let x = 1;
function log(){
console.log(x);
};
function run(fn){
let x = 100;
fn();
}
run(log);//1
})();
The log function is a closure. It refers the x variable from its parent function autorun(), not the one from the run() function.
log功能是一个闭包。 它从其父函数autorun()引用x变量,而不是来自run()函数的x变量。
The closure function has access to the scope in which it was created, not the scope in which it was executed.
闭包函数可以访问创建它的范围,而不是执行它的范围。
The local function scope of autorun() is the lexical scope of the log() function.
autorun()的局部函数作用域是log()函数的词法作用域。
范围链 (Scope chain)
Every scope has a link to the parent scope. When a variable is used, JavaScript looks down the scope chain until it either finds the requested variable or until it reaches the global scope, which is the end of the scope chain.
每个范围都有到父范围的链接。 使用变量时,JavaScript会向下看范围链,直到找到所请求的变量或到达全局范围(范围链的末尾)为止。
看下一个例子 :
let x0 = 0;
(function autorun1(){
let x1 = 1;
(function autorun2(){
let x2 = 2;
(function autorun3(){
let x3 = 3;
console.log(x0 + " " + x1 + " " + x2 + " " + x3);//0 1 2 3
})();
})();
})();
The autorun3() inner function has access to the local x3 variable. It has also access to the x1 and x2 variables from the outer functions and the x0 global variable.
内部函数autorun3()可以访问本地x3变量。 它还可以从外部函数和x0全局变量访问x1和x2变量。
If it cannot find the variable, it will return an error in strict mode.
如果找不到该变量,则它将在严格模式下返回错误。
"use strict";
x = 1;
console.log(x)
//Uncaught ReferenceError: x is not defined
In non-strict mode, referred to as “sloppy mode”, it will do a bad thing and create a global variable.
在非严格模式下(称为“草率模式”),它将做坏事并创建全局变量。
x = 1;
console.log(x); //1
结论 (Conclusion)
Variables defined in global scope are available everywhere in the application.
全局范围内定义的变量可在应用程序中的任何位置使用。
In a module, a variable declared outside any function is hidden and not available to other modules unless it is explicitly exported.
在模块中,在任何函数外部声明的变量都是隐藏的,除非明确导出,否则其他模块无法使用。
Function scope means that parameters and variables defined in a function are visible everywhere within the function
函数范围意味着函数中定义的参数和变量在函数中的任何位置都是可见的
Variables declared with let and const have block scope. var doesn’t have block scope.
用let和const声明的变量具有块范围。 var没有区块范围。
Discover Functional JavaScript was named one of the best new Functional Programming books by BookAuthority!
发现功能JavaScript被称为 BookAuthority最好的新功能编程书籍 !
For more on applying functional programming techniques in React take a look at Functional React.
有关在React中应用函数式编程技术的更多信息,请查看 Functional React 。
Learn functional React, in a project-based way, with Functional Architecture with React and Redux.
通过带有React和Redux的功能架构 ,以基于项目的方式学习功能性React 。
翻译自: https://www.freecodecamp.org/news/an-introduction-to-scope-in-javascript-cbd957022652/
本文深入探讨JavaScript中的不同作用域类型,包括全局作用域、模块作用域、函数作用域、块作用域、词法作用域及范围链的概念。解析变量的生存期、可见性和提升特性,以及如何在不同作用域中正确声明和使用变量。

365

被折叠的 条评论
为什么被折叠?



