>  기사  >  웹 프론트엔드  >  JavaScript의 변수, 범위 및 호이스팅에 대한 깊은 이해

JavaScript의 변수, 범위 및 호이스팅에 대한 깊은 이해

青灯夜游
青灯夜游앞으로
2019-11-25 14:39:392594검색

변수는 많은 프로그래밍 언어의 기본 부분이며 초보자가 배워야 할 첫 번째이자 가장 중요한 개념입니다. 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"

이제 코드에서 사용자 이름을 사용할 수 있습니다. JavaScript는 사용자 이름이 문자열 값 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'

실제 프로그램에서 비밀번호는 데이터베이스에 안전하게 저장될 가능성이 높습니다. 그러나 이 예에서는 변수 값을 업데이트해야 하는 상황을 보여줍니다. 비밀번호 값은 Hunter2였는데, 그 시점부터 JavaScript가 인식하는 값인 Hunter3에 다시 할당했습니다.

이름이 지정된 변수

변수 이름은 JavaScript에서 식별자라고 합니다. JavaScript 구문과 코드 구조를 이해할 때 식별자 이름 지정에 대한 몇 가지 규칙을 논의했습니다. 아래에 요약되어 있습니다: -9), 달러 기호($) 및 밑줄(_)은

  • 으로 구성됩니다. 변수 이름에는 공백 문자(탭 또는 공백)가 포함될 수 없습니다.

    # 🎜🎜#

  • 숫자는 변수 이름의 시작 부분이 될 수 없습니다.
  • #🎜🎜 #

    예약어는 변수 이름으로 사용할 수 없습니다
  • # 🎜🎜#
  • 변수 이름은 대소문자를 구분합니다

  • #🎜 🎜#JavaScript에도 var 또는 let Case를 사용하여 선언된 함수 및 변수 이름에 카멜 케이스를 사용하는 습관이 있습니다(때때로 카멜 케이스 스타일로 지정됨). 이는 첫 번째 단어를 소문자로 만든 다음, 각 후속 단어의 첫 글자를 공백 없이 대문자로 시작하는 방식입니다. 일부 예외를 제외하고 대부분의 비 const 변수는 이 규칙을 따릅니다. const 키워드를 사용하여 선언된 상수 변수의 이름은 일반적으로 대문자입니다.

    이것은 배워야 할 규칙이 많아 보일 수도 있지만 곧 유효하고 일반적인 변수 이름을 작성하는 데 제2의 천성이 될 것입니다.
  • var, let 및 const의 차이점

JavaScript에는 변수를 선언하는 세 가지 다른 키워드가 있어 언어 복잡성이 더욱 가중됩니다. 세 가지의 차이점은 범위, 승격 및 재할당에 따라 다릅니다.

키워드
범위 변수 프로모션 재할당 가능 재정의 가능
var 기능 범위
let 차단 범위 아니요 아니요
const 블록 범위 No 아니요 아니요

您可能想知道应该在自己的程序中使用这三种方法中的哪一种。一个普遍接受的做法是尽可能多地使用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으로 문의하시기 바랍니다. 삭제