首頁 > web前端 > js教程 > 主體

深入理解JavaScript中的變數、範圍和提升

青灯夜游
發布: 2019-11-25 14:39:39
轉載
2601 人瀏覽過

變數是許多程式語言的基本組成部分,也是新手需要學習的第一個也是最重要的概念。 JavaScript中有許多不同的變數屬性,以及命名變數時必須遵循的一些規則。在JavaScript中,有三個關鍵字用於聲明變數——var、let和const——每個關鍵字都會影響程式碼對變數的不同解釋。

深入理解JavaScript中的變數、範圍和提升

本教學將介紹什麼是變量,如何宣告和命名變量,並進一步研究var、let和const之間的差異。我們也將回顧提升的影響以及全域和局部作用域對變數行為的重要性。 【相關課程推薦:JavaScript影片教學

理解變數

#變數是用來儲存值的命名容器。我們可能多次引用的一條資訊可以儲存在一個變數中,以供日後使用或修改。在JavaScript中,變數中包含的值可以是任何JavaScript資料類型,包括數字、字串或物件。

在今天的JavaScript所基於的ECMAScript 2015 (ES6)語言規格之前,只有一種方法來宣告變數-使用var關鍵字。因此,大多數較老的程式碼和學習資源將只對變數使用var。我們將在下面單獨一節討論var、let和const關鍵字之間的差異。

我們可以使用var來示範變數本身的概念。在下面的範例中,我們將聲明一個變量,並為其賦值。

// Assign the string value Sammy to the username identifier
var username = "sammy_shark";
登入後複製

本聲明由以下幾部分組成:

  • 使用var關鍵字聲明變數

  • 變數名(或標識符),使用者名稱

  • 賦值操作,由=語法表示

  • 指派的值「sammy_shark」

現在我們可以在程式碼中使用username。 JavaScript將記住username表示字串值sammy_shark。

// Check if variable is equal to value
if (username === "sammy_shark") {
  console.log(true);
  }
登入後複製

輸出:

true
登入後複製
登入後複製

如前所述,變數可以用來表示任何JavaScript資料型別。在本例中,我們將使用字串、數字、物件、布林值和null值宣告變數。

// Assignment of various variables
var name = "Sammy";
var spartans = 300;
var kingdoms = [ "mammals", "birds", "fish" ];
var poem = { roses: "red", violets: "blue" }; 
var success = true;
var nothing = null;
登入後複製

使用console.log,我們可以看到特定變數中包含的值。

// Send spartans variable to the console
console.log(spartans);
登入後複製

輸出:300

變數將資料儲存在記憶體中,稍後可以存取和修改這些資料。變數也可以重新分配,並給定一個新值。下面的簡化範例示範如何將密碼儲存到變數中,然後進行更新。

//为password变量赋值
var password = "hunter2";
//用一个新值重新分配变量值
password = "hunter3";
console.log(password);
登入後複製

輸出:

'hunter3'
登入後複製

在實際的程式中,密碼很可能安全地儲存在資料庫中。然而,這個例子說明了一種情況,在這種情況下,我們可能需要更新變數的值。 password的值是hunter2,但我們將其重新指派給了hunter3,這是JavaScript從那時起可以辨識的值。

命名變數

變數名稱在JavaScript中稱為識別碼。我們討論了在理解JavaScript語法和程式碼結構時命名標識符的一些規則,總結如下:

  • #變數名稱只能由字母(a-z)、數字(0-9)、美元符號($)和底線(_)組成

  • 變數名稱不能包含任何空白字元(製表符或空格)

  • 數字不能是任何變數的名稱開頭

  • 保留的關鍵字不能用作變數的名稱

  • ##變數名稱區分大小寫

#JavaScript也習慣在使用var或let宣告的函數和變數的名稱中使用駝峰大小寫(有時會作為駝峰大小寫進行樣式化)。這是一種將第一個單字小寫,然後將後面每個單字的第一個字母大寫,中間沒有空格的做法。除了一些例外,大多數非常量的變數都遵循這種約定。使用const關鍵字宣告的常數變數的名稱通常都是大寫的。

這可能看起來像是要學習很多規則,但很快就會成為編寫有效和常規變數名稱的第二天性。

var、let和const之間的區別

JavaScript有三個不同的關鍵字來聲明變量,這給語言增加了額外的複雜性。三者之間的差異是基於範圍、提升和重新分配。

關鍵字
範圍變數提升可以重新分配可以重新定義
var功能範圍YesYesYes
let阻止範圍NoYes#No
const 阻止範圍NoNoNo
#

您可能想知道应该在自己的程序中使用这三种方法中的哪一种。一个普遍接受的做法是尽可能多地使用const,并在循环和重新分配的情况下使用let。通常,在处理遗留代码之外可以避免var。

变量作用域

JavaScript中的作用域是指代码的当前上下文,它决定了变量对JavaScript的可访问性。范围的两种类型是局部的和全局的:

  • 全局变量是在块之外声明的变量

  • 局部变量是在块内声明的变量

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

//初始化一个全局变量
var creature = "wolf";
登入後複製

我们知道变量可以重新分配。使用局部作用域,我们实际上可以创建与外部作用域中的变量同名的新变量,而无需更改或重新分配原始值。

在下面的示例中,我们将创建一个全局species变量。函数内部是一个具有相同名称的局部变量。通过将它们发送到控制台,我们可以看到变量的值如何根据范围而不同,并且原始值不会更改。

//初始化一个全局变量
var species = "human";
function transform() {
//初始化一个局部的、函数作用域的变量
  var species = "werewolf";
  console.log(species);
}
//记录全局和局部变量
console.log(species);
transform();
console.log(species);
登入後複製

输出:

human
werewolf
human
登入後複製

在本例中,局部变量是函数作用域的。使用var关键字声明的变量总是函数作用域,这意味着它们将函数识别为具有独立作用域。因此,这个局部作用域的变量不能从全局作用域访问。

然而,新的关键字let和const是块范围的。这意味着从任何类型的块(包括函数块、if语句、for和while循环)创建一个新的本地范围。

为了说明函数作用域变量和块作用域变量之间的区别,我们将使用let在if块中分配一个新变量。

var fullMoon = true;
//初始化一个全局变量
let species = "human";
if (fullMoon) { 
//初始化一个块范围的变量
  let species = "werewolf";
  console.log(`It is a full moon. Lupin is currently a ${species}.`);
}
console.log(`It is not a full moon. Lupin is currently a ${species}.`);
登入後複製

输出:

It is a full moon. Lupin is currently a werewolf.
It is not a full moon. Lupin is currently a human.
登入後複製

在此示例中,species变量具有一个值global(human),另一个值local(werewolf)。var但是,如果我们使用,则会有不同的结果。

//使用var初始化一个变量
var species = "human";
if (fullMoon) {  
//尝试在一个块中创建一个新变量
  var species = "werewolf";
  console.log(`It is a full moon. Lupin is currently a ${species}.`);
}

console.log(`It is not a full moon. Lupin is currently a ${species}.`);
登入後複製

输出:

It is a full moon. Lupin is currently a werewolf.
It is not a full moon. Lupin is currently a werewolf.
登入後複製

在这个例子的结果中,全局变量和块范围的变量都以相同的值结束。这是因为您不是使用var创建一个新的本地变量,而是在相同的范围内重新分配相同的变量。var不能识别是否属于不同的新范围。通常建议声明块范围的变量,因为它们生成的代码不太可能无意中覆盖变量值。

变量提升

到目前为止,在大多数示例中,我们已经使用var声明了一个变量,并使用一个值初始化了它。在声明和初始化之后,我们可以访问或重新分配变量。

如果我们试图在变量被声明和初始化之前使用它,它将返回undefined。

//在声明变量之前尝试使用它
console.log(x);
/ /变量赋值
var x = 100;
登入後複製

输出:

undefined
登入後複製
登入後複製

但是,如果省略var关键字,就不再声明变量,而是初始化它。它将返回一个ReferenceError并停止脚本的执行。

//在声明变量之前尝试使用它
console.log(x);
//没有var的变量赋值
x = 100;
登入後複製

输出:

ReferenceError: x is not defined
登入後複製

原因在于提升,这是JavaScript的一种行为,其中变量和函数声明被移到它们作用域的顶部。由于只挂起实际声明,而没有初始化,因此第一个示例中的值返回未定义的值。

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

// The code we wrote
console.log(x);
var x = 100;
// How JavaScript interpreted it
var x;
console.log(x);
x = 100;
登入後複製

JavaScript在执行脚本之前将x保存为内存作为变量。 由于它在定义之前仍然被调用,因此结果是未定义的而不是100.但是,它不会导致ReferenceError并停止脚本。

尽管var关键字实际上并未更改var的位置,但这有助于表示提升的工作原理。 但是,这种行为可能会导致问题,因为编写此代码的程序员可能希望x的输出为true,而不是undefined。

在下一个例子中,我们还可以看到提升是如何导致不可预测的结果的:

//在全局范围内初始化x
var x = 100;
function hoist() {
//不应影响编码结果的条件
  if (false) {
      var x = 200;
  }
  console.log(x);
}

hoist();
登入後複製

输出:

undefined
登入後複製
登入後複製

在本例中,我们声明x全局为100。根据if语句,x可以更改为200,但是由于条件为false,所以它不应该影响x的值。

这种不可预测的行为可能会在程序中引起bug。由于let和const是块范围的,所以它们不会以这种方式提升,如下所示。

//在全局范围内初始化x
let x = true;function hoist() {
//在函数作用域中初始化x
 if (3 === 4) {
      let x = false;
  }
  console.log(x);
}

hoist();
登入後複製

输出:

true
登入後複製
登入後複製

变量的重复声明(这在var中是可能的)将在let和const中抛出一个错误。

//试图覆盖用var声明的变量
var x = 1;
var x = 2;

console.log(x);
登入後複製

输出:2

//试图覆盖用let声明的变量
let y = 1;
let y = 2;

console.log(y);
登入後複製

输出:

Uncaught SyntaxError: Identifier 'y' has already been declared
登入後複製

总之,使用var引入的变量有可能受到提升的影响,提升是JavaScript中的一种机制,其中变量声明被保存到内存中。这可能导致代码中出现未定义的变量。let和const的引入解决了这个问题,它在试图在声明变量之前使用该变量或多次声明该变量时抛出一个错误。

常量

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

将所有const标识符都写成大写是常见的约定。这将它们与其他变量值区分开来。

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

//给const赋值
const SPECIES = "human"; 

//尝试重新分配值
SPECIES = "werewolf";

console.log(SPECIES);
登入後複製

输出:

Uncaught TypeError: Assignment to constant variable.
登入後複製

因为不能重新分配const值,所以需要同时声明和初始化它们,否则也会抛出错误。

//声明,但不初始化const
const TODO;

console.log(TODO);
登入後複製

输出:

Uncaught SyntaxError: Missing initializer in const declaration
登入後複製

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

//创建一个具有两个属性的CAR对象
const CAR = {
    color: "blue",
    price: 15000}
//修改CAR的属性
CAR.price = 20000;

console.log(CAR);
登入後複製

输出:

{ color: 'blue', price: 20000 }
登入後複製

常量非常有用,可以让将来的自己和其他程序员清楚地认识到,不应该重新分配预期的变量。如果您希望将来修改某个变量,那么您可能希望使用let来声明该变量。

本文来自 js教程 栏目,欢迎学习!

以上是深入理解JavaScript中的變數、範圍和提升的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:digitalocean.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板