目录
1.1 var声明作用域 var Declaration Scope
1.3 var 声明提升 var Declaration Hoisting
1.4 使用未声明的变量use an undeclared variable
2.3 条件声明 Conditional Declaration
2.4 for 循环中的 let 声明 let Declaration in for Loops
5. 解构赋值 Destructuring Assignment
0.基本常识
0.1变量与常量
计算机编程最基本的技术之一是使用名称names(或标识符identifiers)来表示值values。
将名称绑定到值给我们提供了一种方法来引用该值refer to that value并在我们编写的程序中使用它。当我们这样做的时候,我们通常说我们正在给一个变量赋值assigning a value to a variable。
术语“变量”“variable”意味着可以分配新值new values can be assigned:与变量相关的值可能随着程序运行而变化。
如果我们将一个值永久地赋给一个名称permanently assign a value to a name,那么我们将该名称name称为常数constant,而不是变量variable。
在JavaScript程序中使用变量或常量之前,必须声明它。Before you can use a variable or constant in a JavaScript program, you must declare it.
0.2 作用域scope
变量的作用域是程序源代码中定义变量的区域。使用let和const声明的变量和常量是块作用域。这意味着它们只在let或const语句出现的代码块中定义。
当声明出现在任何代码块之外的顶层时,我们说它是一个全局变量或常量,并具有全局作用域.When a declaration appears at the top level, outside of any code blocks, we say it is a global variable or constant and has global scope
0.3 重复声明
在同一作用域中使用多个let或const声明的相同名称是语法错误 It is a syntax error to use the same name with more than one let or const declaration in the same scope
在嵌套作用域中声明具有相同名称的新变量是合法的(尽管这种做法最好避免) It is legal (though a practice best avoided) to declare a new variable with the same name in a nested scope
const x = 1; // Declare x as a global constant
if (x === 1) {
let x = 2; // Inside a block x can refer to a different value
console.log(x); // Prints 2
}
console.log(x); // Prints 1: we're back in the global scope now
let x = 3; // ERROR! Syntax error trying to re- declare x
1.var
最常见的声明变量的关键字。它没有其他两个关键字的种种限制。这是因为它是传统上在 JavaScript 声明变量的唯一方法
1.1 var声明作用域 var Declaration Scope
函数作用域
使用 **var
**声明的变量在它所声明的整个函数都是可见的
A variable declared with the var
keyword is available from the function it is declared in
它们的作用域是包含他们的函数主体,无论它们在该函数中嵌套的深度如何
they are scoped to the body of the containing function no matter how deeply nested they are inside that function
使用 var在一个函数内部定义一个变量,就意味着该变量将在函数退出时被销毁
function test() {
var message = "hi"; // local variable 局部变量 message 变量是在函数内部使用 var 定义的
}
test(); //函数叫 test(),调用它会创建这个变量并给它赋值。调用之后变量随即被销毁
console.log(message); // error!
但是,在函数内定义变量时省略 var 操作符,可以创建一个全局变量, 但不建议这么做
function test() {
message = "hi"; // global variable **去掉之前的 var 操作符之后,message 就变成了全局变量**
}
test(); //只要调用一次函数 test(),就会定义这个变量,并且可以在函数外部访问到
console.log(message); // "hi"
// myVarVariable *is* visible out here
for (var myVarVariable = 0; myVarVariable < 5; myVarVariable++) {
// myVarVariable is visible to the whole function
}
// myVarVariable *is* visible out here
全局var声明
如果在函数体之外使用 var,它会声明一个全局变量global variable。
用 var 声明的全局变量Globals被实现为全局对象的属性implemented as properties of the global object。
全局对象可以引用为 globalThis //The global object can be referenced as globalThis。 所以如果你写 var x = 2; 在函数之外,就像你写了 globalThis.x = 2;。
使用全局 var 声明创建的属性不能使用 delete 运算符删除。
用 let 和 const 声明的全局变量和常量不是全局对象的属性。
1.2 重复声明
用 var 多次声明同一个变量是合法的。
因为 var 变量具有函数作用域而不是块作用域,所以这种重新声明实际上很常见。
变量 i 经常用于表示整数值,尤其是作为 for 循环的索引变量index variable。在具有多个 for 循环的函数中,通常每个循环都以 for(var i = 0; ....开始
因为var没有将这些变量限定在循环体loop body中,所以每个循环都(无害地)重新声明和初始化相同的变量
1.3 var 声明提升 var Declaration Hoisting
使用这个var声明的变量会自动提升到函数作用域顶部
变量的初始化保留在您编写它的位置,但变量的定义移动到函数的顶部
The initialization of the variable remains where you wrote it, but the definition of the variable moves to the top of the function.
如果初始化代码还没有运行,那么变量的值可能是未定义的,但是如果在变量初始化之前使用它就不会出错
If the initialization code has not run yet, then the value of the variable may be undefined, but you won’t get an error if you use the variable before it is initialized
function foo() {
console.log(age);
var age = 26;
}
foo(); // undefined 不会报错
//因为 ECMAScript 运行时把它看成等价于如下代码:
function foo() {
var age; //把所有变量声明都拉到函数作用域的顶部
console.log(age);
age = 26;
}
foo(); // undefined
//反复多次使用 var 声明同一个变量也没有问题
function foo() {
var age = 16;
var age = 26;
var age = 36;
console.log(age);
}
foo(); // 36
1.4 使用未声明的变量use an undeclared variable
在严格模式中strict mode,如果您尝试使用未声明的变量,则在运行代码时会出现引用错误。
然而,在严格模式之外,如果你给一个没有用 let、const 或 var 声明的名字name赋值,你最终会创建一个新的全局变量。
无论如何深深嵌套在函数和代码块中,它都将是一个全局变量。这几乎肯定不是您想要的,容易出错,并且是使用严格模式的最佳理由之一!
以这种偶然方式创建的全局变量就像用 var 声明的全局变量:它们定义了全局对象的属性。
但与正确的 var 声明定义的属性不同,这些属性可以使用 delete 运算符删除。
2.Let
**let
**声明一个块级作用域的本地变量,并且可选的将其初始化为一个值。
The **let
**statement declares a block-scoped local variable, optionally initializing it to a value.
The declared variable is available from the block it is enclosed in
// myLetVariable is *not* visible out here 在这里 *不能* 被引用
for (let myLetVariable = 0; myLetVariable < 5; myLetVariable++) {
// myLetVariable is only visible in here 只能在这里引用
}
// myLetVariable is *not* visible out here 在这里 *不能* 被引用
let 跟 var 的作用差不多。最明显的区别是,let 声明的范围是块作用域(block scoped),而 var 声明的范围是函数作用域(function scoped)
block-scoped – they only exist within the innermost block that surrounds them
if (true) {
var name = 'Matt';
console.log(name); // Matt
}
console.log(name); // Matt
if (true) {
let age = 26;
console.log(age); // 26
}
console.log(age); // ReferenceError: age is not defined
//the age variable cannot be referenced outside the if block because its scope does not extend outside the block
//age 变量之所以不能在 if 块外部被引用,是因为它的作用域仅限于该块内部
块作用域是函数作用域的子集,因此适用于 var 的作用域限制同样也适用于 let
2.1 暂时性死区 Temporal Dead Zone
let 与 var 的另一个重要的区别,就是 let 声明的变量不会在作用域中被提升
// name 会被提升
console.log(name); // undefined
var name = 'Matt';
// age 不会被提升
console.log(age); // ReferenceError:age 没有定义
let age = 26;
When parsing the code, JavaScript engines will still be aware of the let declarations that appear later in a block, but these variables will be unable to be referenced in any way before the actual declaration occurs. The segment of execution that occurs before the declaration is referred to as the “temporal dead zone,” and any attempted references to these variables will throw a ReferenceError.
在解析代码时,JavaScript 引擎也会注意出现在块后面部分的 let 声明,只不过在此之前不能以任何方式来引用未声明的变量。在 let 声明之前的执行瞬间被称为“暂时性死区”