了解 JavaScript 中的变量、作用域和起重功能

介绍

_Variables是许多编程语言的基本组成部分,是初学者编码者学习的第一个和最重要的概念之一.在JavaScript中有许多不同的变量属性,以及在命名它们时必须遵循的几条规则。

本教程将涵盖变量是什么,如何声明和命名它们,并更仔细地研究varletconst之间的区别。

变量理解

一个 变量是用于存储值的命名容器。我们可能多次参考的信息可以存储在变量中以供以后使用或修改。

ECMAScript 2015 (ES6)语言规格之前,今天的JavaScript是基于的,只有一个方法来声明变量 - 使用var关键字. 因此,大多数旧代码和学习资源只会使用var变量。

我们可以使用var来证明变量本身的概念,在下面的示例中,我们将 declare 变量,并 assign 值。

1// Assign the string value Sammy to the username identifier
2var username = "sammy_shark";

该声明由几个部分组成:

  • 使用 var 关键字的变量声明
  • 变量名称(或标识符)、 username
  • 指定的操作,由 = 语法
  • 被分配的值, "sammy_shark"

现在我们可以在代码中使用用户名。JavaScript会记住用户名代表字符串值sammy_shark

1// Check if variable is equal to value
2if (username === "sammy_shark") {
3  console.log(true);
4}
1[secondary_label Output]
2true

如前所述,变量可以用来表示任何JavaScript数据类型. 在本示例中,我们将声明具有字符串、数字、对象、布尔和无值的变量。

1// Assignment of various variables
2var name = "Sammy";
3var spartans = 300;
4var kingdoms = [ "mammals", "birds", "fish" ];
5var poem = { roses: "red", violets: "blue" }; 
6var success = true;
7var nothing = null;

使用 console.log,我们可以看到特定变量中包含的值。

1// Send spartans variable to the console
2console.log(spartans);
1[secondary_label Output]
2300

变量在内存中存储数据,可以随后访问和修改。 变量也可以重新分配并给出新的值。 下面的简化示例展示了如何将密码存储到变量并更新。

1// Assign value to password variable
2var password = "hunter2";
3
4// Reassign variable value with a new value
5password = "hunter3";
6
7console.log(password);
1[secondary_label Output]
2'hunter3'

在一个实际的程序中,密码很可能安全地存储在数据库中,但是,这个例子说明了我们可能需要更新变量的值的情况。

变量名称

在 JavaScript 中,变量名称被称为 _identifiers。我们在 理解 JavaScript 的语法和代码结构中讨论了几个命名标识符的规则,这些规则总结在这里:

JavaScript 也有使用骆驼案例的惯例(有时以 camelCase 来形容)在函数和变量名称中声明为varlet 这是写下第一个单词的惯例,然后用每个随后的单词的第一个字母进行资本化,在它们之间没有空间。

这可能看起来像有很多规则要学习,但写有效和常规变量名称很快就会成为第二自然。

varletconst的区别

JavaScript 有三个不同的关键字来声明一个变量,这为语言添加了一层额外的复杂性。

KeywordScopeHoistingCan Be ReassignedCan Be Redeclared
varFunction scopeYesYesYes
letBlock scopeNoYesNo
constBlock scopeNoNoNo

你可能会想知道你应该在自己的程序中使用哪个三种方法。 一个常见的做法是尽可能地使用const,并在循环和重新分配的情况下使用let

变量范围

_Scope_在JavaScript中是指当前的代码背景,它决定了变量对JavaScript的可访问性。

  • 全球变量是区块 之外声明的变量 本地变量是区块 内部声明的变量

在下面的例子中,我们将创建一个全球变量。

1// Initialize a global variable
2var creature = "wolf";

使用本地范围,我们实际上可以创建与外部范围中的变量相同名称的新变量,而不改变或重新分配原始值。

在下面的示例中,我们将创建一个全球的物种变量. 函数内有一个具有相同名称的本地变量. 通过将其发送到控制台,我们可以看到该变量的值如何不同,取决于范围,并且原始值不会改变。

 1// Initialize a global variable
 2var species = "human";
 3
 4function transform() {
 5  // Initialize a local, function-scoped variable
 6  var species = "werewolf";
 7  console.log(species);
 8}
 9
10// Log the global and local variable
11console.log(species);
12transform();
13console.log(species);
1[secondary_label Output]
2human
3werewolf
4human

在本示例中,本地变量是 function-scoped. 用var关键字声明的变量总是具有函数范围,这意味着它们将函数识别为具有单独的范围。

然而,新的关键字让我们假设区块范围的,这意味着从任何类型的区块中创建一个新的本地范围,包括函数块、如果陈述和循环。

为了说明函数和区块范围变量之间的差异,我们将使用在一个如果块中分配一个新的变量。

 1var fullMoon = true;
 2
 3// Initialize a global variable
 4let species = "human";
 5
 6if (fullMoon) {
 7  // Initialize a block-scoped variable
 8  let species = "werewolf";
 9  console.log(`It is a full moon. Lupin is currently a ${species}.`);
10}
11
12console.log(`It is not a full moon. Lupin is currently a ${species}.`);
1[secondary_label Output]
2It is a full moon. Lupin is currently a werewolf.
3It is not a full moon. Lupin is currently a human.

在这个例子中,物种变量有一个值在全球()和另一个值在本地()。

 1// Use var to initialize a variable
 2var species = "human";
 3
 4if (fullMoon) {
 5  // Attempt to create a new variable in a block
 6  var species = "werewolf";
 7  console.log(`It is a full moon. Lupin is currently a ${species}.`);
 8}
 9
10console.log(`It is not a full moon. Lupin is currently a ${species}.`);
1[secondary_label Output]
2It is a full moon. Lupin is currently a werewolf.
3It is not a full moon. Lupin is currently a werewolf.

在此示例中,全球变量和区块变量最终都具有相同的值,‘werewolf’. 这是因为,而不是使用‘var’创建一个新的本地变量,您正在重新分配相同的变量在相同的范围内。

主持人

在迄今为止的大多数示例中,我们已经使用了var来声明变量,并且我们已将其以值初始化。

如果我们在声明和初始化之前尝试使用变量,它将返回未定义

1// Attempt to use a variable before declaring it
2console.log(x);
3
4// Variable assignment
5var x = 100;
1[secondary_label Output]
2undefined

但是,如果我们忽略了var的关键字,我们不再声明变量,只会初始化它,它会返回ReferenceError,并停止脚本的执行。

1// Attempt to use a variable before declaring it
2console.log(x);
3
4// Variable assignment without var
5x = 100;
1[secondary_label Output]
2ReferenceError: x is not defined

原因是由于 hoisting,这是JavaScript的行为,其中变量和函数声明被移动到其范围的顶部. 因为只有实际声明被提升,而不是初始化,所以第一个示例中的值返回未定义

为了更清楚地展示这一概念,以下是我们编写的代码以及JavaScript如何真正解释它。

1// The code we wrote
2console.log(x);
3var x = 100;
4
5// How JavaScript interpreted it
6var x;
7console.log(x);
8x = 100;

JavaScript 在执行脚本之前将x保存到记忆中作为变量,因为它在被定义之前仍然被调用,所以结果是未定义而不是100。然而,它不会导致参考错误并停止脚本。尽管var关键字实际上没有改变var的位置,但这是一个有用的表述。这种行为可能会导致问题,尽管如此,因为编写这个代码的程序员很可能希望x的输出是100,而不是未定义

我们也可以在下面的例子中看到,如何提高可以导致不可预测的结果:

 1// Initialize x in the global scope
 2var x = 100;
 3
 4function hoist() {
 5  // A condition that should not affect the outcome of the code
 6  if (false) {
 7    var x = 200;
 8  }
 9  console.log(x);
10}
11
12hoist();
1[secondary_label Output]
2undefined

在本示例中,我们声明x100在全球范围内。根据if语句,x可能会变为200,但由于条件是false,它不应该影响x的值。

这种不可预测的行为可能会导致程序中的错误,因为让我们假设是封锁的,因此它们不会以这种方式升高,如下所示。

 1// Initialize x in the global scope
 2let x = true;
 3
 4function hoist() {
 5  // Initialize x in the function scope
 6  if (3 === 4) {
 7    let x = false;
 8  }
 9  console.log(x);
10}
11
12hoist();
1
2[secondary_label 输出]
3

Duplicate declaration of variables, which is possible with var, will throw an error with let and const.

1// Attempt to overwrite a variable declared with var
2var x = 1;
3var x = 2;
4
5console.log(x);
1[secondary_label Output]
22
1// Attempt to overwrite a variable declared with let
2let y = 1;
3let y = 2;
4
5console.log(y);
1[secondary_label Output]
2Uncaught SyntaxError: Identifier 'y' has already been declared

要总结一下,用var引入的变量有可能受到提升的影响,这是JavaScript中的一个机制,其中变量声明被保存到内存中,这可能导致一个代码中未定义的变量。

常态

许多编程语言都具有 constants,这些值是无法修改或更改的值。在JavaScript中,const 标识符是根据常数建模的,并且不能重新分配给const 的值。

通常会将所有const标识符写在上方,这将它们标记为易于区分于其他变量值。

在下面的示例中,我们将变量SPECIES作为一个常数与关键字const初始化,试图重新分配变量会导致错误。

1// Assign value to const
2const SPECIES = "human"; 
3
4// Attempt to reassign value
5SPECIES = "werewolf";
6
7console.log(SPECIES);
1[secondary_label Output]
2Uncaught TypeError: Assignment to constant variable.

由于const值不能重新分配,因此它们需要同时声明和初始化,否则也会引发错误。

1// Declare but do not initialize a const
2const TODO;
3
4console.log(TODO);
1[secondary_label Output]
2Uncaught SyntaxError: Missing initializer in const declaration

在编程中不能更改的值被称为 immutable,而可以更改的值是 mutable.虽然const值不能重新分配,但它们是可变的,因为可以更改用const声明的对象的属性。

 1// Create a CAR object with two properties
 2const CAR = {
 3    color: "blue",
 4    price: 15000
 5}
 6
 7// Modify a property of CAR
 8CAR.price = 20000;
 9
10console.log(CAR);
1[secondary_label Output]
2{ color: 'blue', price: 20000 }

常数有助于向您未来的自我和其他与您合作的项目编程人员明确,不应重新分配预期变量. 如果您预计未来可能会更改变量,您可能希望使用让我们来宣布变量。

结论

在本教程中,我们讨论了变量是什么,变量命名规则,以及如何重新分配变量值,我们还了解了范围和提升,原始var关键字的一些局限性,以及letconst如何纠正这些问题。

要比较如何在其他语言中使用变量,您可以阅读我们的教程如何在Python中使用变量 3](https://andsky.com/tech/tutorials/how-to-use-variables-in-python-3)

Published At
Categories with 技术
comments powered by Disqus