Thứ ba, 20/02/2018 | 00:00 GMT+7

Hiểu các biến, phạm vi và lưu trữ trong JavaScript

Biến là một phần cơ bản của nhiều ngôn ngữ lập trình, và là một trong những khái niệm đầu tiên và quan trọng nhất đối với các lập trình viên mới làm quen. Có một số thuộc tính khác nhau của các biến trong JavaScript, cũng như một số luật phải tuân theo khi đặt tên cho chúng. Trong JavaScript, có ba từ khóa được sử dụng để khai báo một biến - var , letconst - và mỗi từ khóa ảnh hưởng đến cách mã sẽ diễn giải biến khác nhau.

Hướng dẫn này sẽ trình bày các biến là gì, cách khai báo và đặt tên cho chúng, đồng thời xem xét kỹ hơn sự khác biệt giữa var , letconst . Ta cũng sẽ xem xét các tác động của việc nâng cấp và tầm quan trọng của phạm vi global và local đối với hành vi của một biến.

Hiểu các biến

Một biến là một containers được đặt tên được sử dụng để lưu trữ các giá trị. Một phần thông tin mà ta có thể tham chiếu nhiều lần có thể được lưu trữ trong một biến để sử dụng hoặc sửa đổi sau này. Trong JavaScript, giá trị chứa bên trong một biến có thể là bất kỳ kiểu dữ liệu JavaScript nào, bao gồm một số, chuỗi hoặc đối tượng.

Trước đặc tả ngôn ngữ ECMAScript 2015 (ES6) mà JavaScript ngày nay dựa trên, chỉ có một cách để khai báo một biến - sử dụng từ khóa var . Do đó, hầu hết các mã cũ và tài nguyên học tập sẽ chỉ sử dụng var cho các biến. Ta sẽ xem xét sự khác biệt giữa các từ khóa var , letconst trong phần riêng của nó bên dưới.

Ta có thể sử dụng var để chứng minh khái niệm của chính một biến. Trong ví dụ dưới đây, ta sẽ khai báo một biến và gán giá trị cho nó.

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

Lệnh này bao gồm một số phần:

  • Khai báo một biến bằng từ khóa var
  • Tên biến (hoặc số nhận dạng), username
  • Thao tác gán, được biểu diễn bằng cú pháp =
  • Giá trị đang được chỉ định, "sammy_shark"

Bây giờ ta có thể sử dụng username trong mã. JavaScript sẽ nhớ rằng username đại diện cho giá trị chuỗi sammy_shark .

// Check if variable is equal to value if (username === "sammy_shark") {   console.log(true); } 
Output
true

Như đã đề cập trước đây, các biến được dùng để đại diện cho bất kỳ kiểu dữ liệu JavaScript nào. Trong ví dụ này, ta sẽ khai báo các biến có giá trị chuỗi, số, đối tượng, Boolean và 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; 

Sử dụng console.log , ta có thể thấy giá trị chứa trong một biến cụ thể.

// Send spartans variable to the console console.log(spartans); 
Output
300

Các biến lưu trữ dữ liệu trong bộ nhớ mà sau này có thể được truy cập và sửa đổi. Các biến cũng có thể được gán lại và cho một giá trị mới. Ví dụ đơn giản bên dưới minh họa cách password có thể được lưu trữ vào một biến và sau đó được cập nhật.

// Assign value to password variable var password = "hunter2";  // Reassign variable value with a new value password = "hunter3";  console.log(password); 
Output
'hunter3'

Trong một chương trình thực tế, password rất có thể sẽ được lưu trữ an toàn trong database . Tuy nhiên, ví dụ này minh họa một tình huống mà ta có thể cần cập nhật giá trị của một biến. Giá trị của passwordhunter2 , nhưng ta đã gán lại nó cho hunter3 , đây là giá trị mà JavaScript nhận ra từ thời điểm đó trở đi.

Đặt tên biến

Tên biến được gọi là số nhận dạng trong JavaScript. Ta đã thảo luận về một số luật đặt tên số nhận dạng trong Tìm hiểu cú pháp và cấu trúc mã trong JavaScript , được tóm tắt ở đây:

  • Tên biến chỉ có thể bao gồm các chữ cái ( az ), số ( 0-9 ), ký hiệu dấu đô la ( $ ) và dấu gạch dưới ( _ )
  • Tên biến không được chứa bất kỳ ký tự khoảng trắng nào (tab hoặc dấu cách)
  • Các số không được bắt đầu bằng tên của bất kỳ biến nào
  • Có một số từ khóa dành riêng không thể được sử dụng làm tên của một biến
  • Tên biến phân biệt chữ hoa chữ thường

JavaScript cũng có quy ước sử dụng chữ hoa camel (đôi khi được cách điệu thành camelCase) trong tên của các hàm và biến được khai báo bằng var hoặc let . Đây là cách viết chữ thường của từ đầu tiên, sau đó viết hoa chữ cái đầu tiên của mỗi từ tiếp theo mà không có khoảng cách giữa chúng. Hầu hết các biến không phải là hằng số sẽ tuân theo quy ước này, với một số ngoại lệ. Tên của các biến không đổi, được khai báo bằng từ khóa const , thường được viết bằng tất cả các chữ hoa.

Điều này có vẻ giống như rất nhiều luật để học, nhưng nó sẽ rất nhanh chóng trở thành bản chất thứ hai để viết các tên biến hợp lệ và quy ước.

Sự khác biệt giữa var , letconst

JavaScript có ba từ khóa khác nhau để khai báo một biến, điều này bổ sung thêm một lớp phức tạp cho ngôn ngữ. Sự khác biệt giữa ba yếu tố này dựa trên phạm vi, sự nâng cấp và sự phân công lại.

Từ khóa Phạm vi Cẩu Có thể được giao lại Có thể được khai báo lại
var Phạm vi chức năng Đúng Đúng Đúng
let Phạm vi khối Không Đúng Không
const Phạm vi khối Không Không Không

Bạn có thể tự hỏi bạn nên sử dụng cái nào trong ba cái nào trong các chương trình của bạn . Một phương pháp thường được chấp nhận là sử dụng const càng nhiều càng tốt, và let trong trường hợp lặp lại và gán lại. Nói chung, có thể tránh được var bên ngoài làm việc trên mã kế thừa.

Phạm vi biến đổi

Phạm vi trong JavaScript đề cập đến ngữ cảnh hiện tại của mã, điều này xác định khả năng truy cập của các biến đối với JavaScript. Hai loại phạm vi là cục bộ global :

  • Biến toàn cục là những biến được khai báo bên ngoài một khối
  • Biến local là những biến được khai báo bên trong một khối

Trong ví dụ dưới đây, ta sẽ tạo một biến toàn cục.

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

Ta đã biết rằng các biến có thể được gán lại. Sử dụng phạm vi local , ta có thể tạo các biến mới có cùng tên với một biến trong phạm vi bên ngoài mà không cần thay đổi hoặc gán lại giá trị ban đầu.

Trong ví dụ dưới đây, ta sẽ tạo một biến species toàn cục. Trong hàm là một biến local có cùng tên. Bằng cách gửi chúng đến console , ta có thể thấy giá trị của biến khác nhau như thế nào tùy thuộc vào phạm vi và giá trị ban đầu không bị thay đổi.

// Initialize a global variable var species = "human";  function transform() {   // Initialize a local, function-scoped variable   var species = "werewolf";   console.log(species); }  // Log the global and local variable console.log(species); transform(); console.log(species); 
Output
human werewolf human

Trong ví dụ này, biến local có phạm vi chức năng . Các biến được khai báo với từ khóa var luôn nằm trong phạm vi hàm, nghĩa là chúng nhận ra các hàm có phạm vi riêng biệt. Do đó không thể truy cập biến phạm vi local này từ phạm vi toàn cục.

Tuy nhiên, các từ khóa mới letconstphạm vi khối . Điều này có nghĩa rằng một, phạm vi local mới được tạo ra từ bất kỳ loại khối, bao gồm các khối chức năng, if báo cáo, và forwhile vòng lặp.

Để minh họa sự khác biệt giữa function- và biến khối scoped, ta sẽ gán một biến mới trong một if khối sử dụng let .

var fullMoon = true;  // Initialize a global variable let species = "human";  if (fullMoon) {   // Initialize a block-scoped variable   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}.`); 
Output
It is a full moon. Lupin is currently a werewolf. It is not a full moon. Lupin is currently a human.

Trong ví dụ này, biến species có một giá trị trên phạm vi global ( human ) và một giá trị khác tại local ( werewolf ). Tuy nhiên, nếu ta sử dụng var , sẽ có một kết quả khác.

// Use var to initialize a variable var species = "human";  if (fullMoon) {   // Attempt to create a new variable in a block   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}.`); 
Output
It is a full moon. Lupin is currently a werewolf. It is not a full moon. Lupin is currently a werewolf.

Trong kết quả của ví dụ này, cả biến toàn cục và biến phạm vi khối đều có cùng giá trị, là ma werewolf . Điều này là do thay vì tạo một biến local mới với var , bạn đang gán lại cùng một biến trong cùng một phạm vi. var không nhận ra if là một phần của một phạm vi mới, khác. Thông thường, bạn nên khai báo các biến có phạm vi khối, vì chúng tạo ra mã ít có khả năng vô tình overrides các giá trị của biến.

Cẩu

Trong hầu hết các ví dụ cho đến nay, ta đã sử dụng var để khai báo một biến và ta đã khởi tạo nó với một giá trị. Sau khi khai báo và khởi tạo, ta có thể truy cập hoặc gán lại biến.

Nếu ta cố gắng sử dụng một biến trước khi nó được khai báo và khởi tạo, nó sẽ trả về undefined .

// Attempt to use a variable before declaring it console.log(x);  // Variable assignment var x = 100; 
Output
undefined

Tuy nhiên, nếu ta bỏ qua từ khóa var , ta sẽ không khai báo biến nữa mà chỉ khởi tạo nó. Nó sẽ trả về một ReferenceError và tạm dừng việc thực thi tập lệnh.

// Attempt to use a variable before declaring it console.log(x);  // Variable assignment without var x = 100; 
Output
ReferenceError: x is not defined

Lý do cho điều này là do cẩu, một hành vi của JavaScript trong đó biến và chức năng khai báo được chuyển đến phía trên cùng của phạm vi của họ. Vì chỉ có khai báo thực tế được lưu trữ, không phải là khởi tạo, giá trị trong ví dụ đầu tiên trả về undefined .

Để chứng minh khái niệm này rõ ràng hơn, dưới đây là đoạn mã ta đã viết và cách JavaScript thực sự diễn giải nó.

// The code we wrote console.log(x); var x = 100;  // How JavaScript interpreted it var x; console.log(x); x = 100; 

JavaScript đã lưu x vào bộ nhớ dưới dạng một biến trước khi thực thi tập lệnh. Vì nó vẫn được gọi trước khi nó được xác định, nên kết quả là undefined và không phải là 100 . Tuy nhiên, nó không gây ra ReferenceError và tạm dừng tập lệnh. Mặc dù từ khóa var không thực sự thay đổi vị trí của var , nhưng đây là một trình bày hữu ích về cách hosts hoạt động. Tuy nhiên, hành vi này có thể gây ra sự cố, bởi vì lập trình viên đã viết mã này có thể mong đợi kết quả kết quả của xtrue , khi thay vào đó nó là undefined .

Ta cũng có thể thấy cách hoạt động cẩu có thể dẫn đến kết quả không thể đoán trước trong ví dụ tiếp theo:

// Initialize x in the global scope var x = 100;  function hoist() {   // A condition that should not affect the outcome of the code   if (false) {     var x = 200;   }   console.log(x); }  hoist(); 
Output
undefined

Trong ví dụ này, ta đã khai báo x100 trên phạm vi global . Tùy thuộc vào một if tuyên bố, x có thể thay đổi để 200 , nhưng vì điều kiện là false nó không nên đã ảnh hưởng đến giá trị của x . Thay vào đó, x được đưa lên đầu hàm hoist() và giá trị trở thành undefined .

Loại hành vi không thể đoán trước này có thể gây ra lỗi trong chương trình. Vì letconst là phạm vi khối, chúng sẽ không treo theo cách này, như được thấy bên dưới.

// Initialize x in the global scope let x = true;  function hoist() {   // Initialize x in the function scope   if (3 === 4) {     let x = false;   }   console.log(x); }  hoist(); 
Output
true

Khai báo trùng lặp của các biến, có thể xảy ra với var , sẽ gây ra lỗi với letconst .

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

Tóm lại, các biến được giới thiệu với var có khả năng bị ảnh hưởng bởi tính năng lưu trữ, một cơ chế trong JavaScript trong đó các khai báo biến được lưu vào bộ nhớ. Điều này có thể dẫn đến các biến không xác định trong mã của một người. Sự ra đời của letconst giải quyết vấn đề này bằng cách tạo ra một lỗi khi cố gắng sử dụng một biến trước khi khai báo nó hoặc cố gắng khai báo một biến nhiều lần.

Hằng số

Nhiều ngôn ngữ lập trình có các hằng số , là các giá trị không thể sửa đổi hoặc thay đổi. Trong JavaScript, các const định được mô hình hóa sau khi hằng, và các giá trị được gán cho một const không thể được bố trí.

Quy ước chung là viết tất cả các định danh const bằng chữ hoa. Điều này đánh dấu chúng là dễ phân biệt với các giá trị biến khác.

Trong ví dụ dưới đây, ta khởi tạo biến SPECIES dưới dạng một hằng số với từ khóa const . Cố gắng gán lại biến sẽ dẫn đến lỗi.

// Assign value to const const SPECIES = "human";   // Attempt to reassign value SPECIES = "werewolf";  console.log(SPECIES); 
Output
Uncaught TypeError: Assignment to constant variable.

Vì các giá trị const không thể được gán lại, chúng cần được khai báo và khởi tạo cùng một lúc, hoặc cũng sẽ tạo ra một lỗi.

// Declare but do not initialize a const const TODO;  console.log(TODO); 
Output
Uncaught SyntaxError: Missing initializer in const declaration

Các giá trị không thể thay đổi trong lập trình được gọi là bất biến , trong khi các giá trị có thể thay đổi là có thể thay đổi . Mặc dù các giá trị const không thể được gán lại nhưng chúng có thể thay đổi được vì có thể sửa đổi các thuộc tính của các đối tượng được khai báo với const .

// Create a CAR object with two properties const CAR = {     color: "blue",     price: 15000 }  // Modify a property of CAR CAR.price = 20000;  console.log(CAR); 
Output
{ color: 'blue', price: 20000 }

Hằng số hữu ích để làm rõ cho tương lai của bạn và các lập trình viên khác đang làm việc trong một dự án với bạn rằng biến dự định không nên được gán lại. Nếu bạn mong đợi rằng một biến có thể được sửa đổi trong tương lai, bạn có thể sẽ muốn sử dụng let để khai báo biến thay thế.

Kết luận

Trong hướng dẫn này, ta đã xem xét biến là gì, các luật đặt tên biến và cách gán lại giá trị của biến. Ta cũng đã tìm hiểu về phạm vi và lưu trữ, một số hạn chế của từ khóa var ban đầu, cũng như cách letconst khắc phục những vấn đề đó.

Để so sánh cách các biến được sử dụng trong các ngôn ngữ khác, bạn có thể đọc hướng dẫn của ta về “ Cách sử dụng biến trong Python 3 ”.


Tags:

Các tin liên quan

Tìm hiểu Nguyên mẫu và Kế thừa trong JavaScript
2018-01-12
Khám phá đối tượng ngày JavaScript
2017-12-06
chuỗi con so với chuỗi con trong JavaScript
2017-11-06
Hiểu Ngày và Giờ trong JavaScript
2017-10-19
Cách xác định các hàm trong JavaScript
2017-10-09
Vòng lặp Đối với, Đối với ... Trong vòng lặp và Đối với ... Trong Vòng lặp trong JavaScript
2017-10-02
Vòng lặp Đối với, Đối với ... Trong vòng lặp và Đối với ... Trong Vòng lặp trong JavaScript
2017-10-02
Xử lý các đối tượng trong JavaScript với Object.assign, Object.keys và hasOwnProperty
2017-09-29
Sử dụng Vòng lặp While và Vòng lặp Do ... Trong khi trong JavaScript
2017-09-27
Sử dụng Vòng lặp While và Vòng lặp Do ... Trong khi trong JavaScript
2017-09-27