JavaScript là một trong những ngôn ngữ được sử dụng nhiều nhất trên Internet, nắm vững các loại có thể thay đổi và không thể thay đổi trong JavaScript là một điểm cộng để trả lời câu hỏi phỏng vấn phổ biến này trong lập trình. Trong bài viết này, chúng tôi sẽ trả lời câu hỏi này bằng các ví dụ để làm rõ khái niệm
Mục lục ẩn
1 Các loại có thể thay đổi và không thể thay đổi
2 Tại sao việc không biết các loại Có thể thay đổi và Không thể thay đổi trong JavaScript có thể khiến bạn gặp rắc rối.
3 Chúng ta có thể tạo các đối tượng JavaScript bất biến không?
Các loại có thể thay đổi và không thể thay đổi
Vậy các loại có thể thay đổi và không thay đổi trong JavaScript là gì?
Các đối tượng có thể thay đổi là các đối tượng có giá trị có thể thay đổi sau khi được tạo, trong khi các đối tượng không thể thay đổi là những đối tượng có giá trị không thể thay đổi sau khi được tạo. Trong JavaScript số, chuỗi, null, không xác định và Booleans là các kiểu nguyên thủy không thay đổi. Các đối tượng, mảng, hàm, lớp, bản đồ và tập hợp có thể thay đổi
Các loại có thể thay đổi có các danh tính riêng và được so sánh bằng tham chiếu, nghĩa là các biến giữ các tham chiếu đến các đối tượng hoặc đúng hơn là chúng trỏ đến vị trí bộ nhớ của một đối tượng. Các loại bất biến không có danh tính riêng do đó được so sánh theo giá trị, tôi. e. giá trị trong biến chứ không phải vị trí mà chúng đang tham chiếu
Đây là một đoạn mã để hiển thị ý nghĩa của chúng tôi đối với các đối tượng có thể thay đổi
var car = { color: 'red', tyres: '4' } var anotherCar = car; //here we assign the value of car to anotherCar. car.color = 'blue'; //we alter a value in the original object console.log[anotherCar.color]; //this shows blue because it is referencing the memory location of the car object. console.log[car === anotherCar] //true [because comparison is by reference]
Ý nghĩa của các loại có thể thay đổi là khi chúng ta thay đổi giá trị của một biến, các thay đổi sẽ áp dụng cho tất cả các tham chiếu đến biến đó
Đây là một đoạn mã để hiển thị những gì chúng tôi muốn nói về các chuỗi là bất biến
var aString = "This is a string"; var bString = aString; //now we alter aString aString = "The string has changed"; console.log[aString]; //The string has changed console.log[bString]; //This is a string console.log[aString === bString]; //false
Khi bạn sửa đổi một chuỗi, một chuỗi hoàn toàn mới sẽ được tạo và tên của biến được gán cho tham chiếu bộ nhớ của nó. Không có cách nào thay đổi trạng thái bên trong của một loại bất biến, vì vậy biến chỉ cần được gán lại cho một tham chiếu mới. Tương tự với các số
Hãy xác định và gán giá trị cho một số biến khi bắt đầu tập lệnh của chúng ta, sau đó tạo một số hàm để xem liệu chúng ta có thể thao tác các giá trị trong biến của mình không
// The Primitive types [We'll go with numbers and strings] let someNumber = 50; let someString = "This is an immutable string."; //Non primitive types [We'll go with arrays and objects] let someArray = [1,2,3,4,5,6]; let somePersonObject = { name:"Christole", age:40, gender:"female" } // Defining a function that, ideally should change the Primitive value function addSomeNumber[someNumber, valueToAdd] { someNumber += valueToAdd; console.log[someNumber]; } //Defining a function that, ideally should change the string function changeString[someString] { someString += " Maybe I'm not an immutable string"; console.log[someString]; } //Defining a function that should change the array function addToArray[someArray] { someArray.push[500000]; console.log[someArray]; } //Defining a function that should change the age of a person in the person object function GrownOlder[somePersonObject] { somePersonObject.age=41; console.log[somePersonObject]; }
Hãy đi qua mã từng bước.
Khi chúng ta chạy hàm addSomeNumber[someNumber, 2], bằng cách truyền vào someNumber làm tham số, nó sẽ thực hiện các thao tác trên biến này. Trong phạm vi chức năng của nó, giá trị của someNumber sẽ là 52, i. e. [50+2]. Lý tưởng nhất là chúng ta mong đợi biến bên ngoài phạm vi chức năng cũng thay đổi thành 52, nhưng điều đó không xảy ra. Vì vậy, sau khi bạn chạy hàm addSomeNumber[someNumber, 2] rồi chạy
console.log[someNumber] // the value will still be 50.
Tình huống tương tự cũng xảy ra với biến someString và hàm changeString[someString]. Điều này có nghĩa là chúng ta có thể chạy hàm này nhiều lần mà vẫn nhận được kết quả tương tự, vì các giá trị ban đầu trong chuỗi hoặc số không bị thay đổi. Còn đối tượng và mảng thì sao?
Khi chúng ta chạy hàm addToArray[someArray], bằng cách chuyển vào mảng ban đầu có 6 mục, giờ nó sẽ có 7 mục. Khi bạn chạy giao diện điều khiển. log[someArray] bây giờ nó sẽ có 1,2,3,4,5,6,500000. Điều này là do một mảng có thể thay đổi được;
Khi chúng tôi chạy chức năng GrownOlder[somePersonObject], nó sẽ cập nhật tuổi của người đó thành 41. Vì các biến đối tượng là theo tham chiếu, nên đối tượng được thay đổi trên toàn cầu. Một cuộc gọi khác đến đối tượng từ bất kỳ đâu trong mã của bạn sẽ có các giá trị được cập nhật. Điều này giải thích ý nghĩa của chúng ta đối với các đối tượng có thể thay đổi, giá trị ban đầu có thể được sửa đổi. Bạn cũng có thể thêm giá trị vào đối tượng. Giả sử chúng ta muốn thêm trình độ học vấn, sau đó chúng ta có thể viết somePersonObject. học vấn = “tiến sĩ”;
Một sự nhầm lẫn khác xảy ra khi làm việc với từ khóa const. Lý tưởng nhất là khi một kiểu dữ liệu nguyên thủy [chuỗi, số] được khai báo bằng từ khóa const, thì bạn sẽ không thể gán lại giá trị cho nó. Khai báo một đối tượng với từ khóa const không thay đổi hành vi của tính biến đổi của nó. Nó chỉ ngăn bạn gán biến này cho thứ khác. Hãy xem xét ví dụ sau;
const obj = { number:5 } const objCopy=obj; //do some increments on the object obj.number++;
Khi bạn hiển thị các giá trị đối tượng, nó sẽ có số là 6, mặc dù bạn đã khai báo nó với từ khóa const. Chúng tôi đã gán obj cho objCopy, nếu bạn hiển thị giá trị của objCopy, nó cũng sẽ có số là 6
Điều quan trọng là phải nhận thức được sự đột biến này khi làm việc với các đối tượng. Khi hai hoặc nhiều đối tượng tham chiếu đến một đối tượng, sự thay đổi thuộc tính của một đối tượng được phản ánh trong tất cả các đối tượng khác. Điều này có thể được giải thích bằng mã này;
const obj1 = {name:"James"} const obj2 = obj1; obj2.name = "Jack"; //If we display the values of obj1, it will have Jack as name. console.log[obj1.name]; // Jack //let's declare another obj and assign obj1 to it const obj3 = obj1; //We create a new field in obj3 obj3.age = 20; //the age field is reflected on all instances of the obj //now if we try to display the values of obj1, it will have the new field as well. console.log[obj1]; // {name:"Jack", age:20}
Tại sao không biết các loại Mutable và Immutable trong JavaScript có thể khiến bạn gặp rắc rối
Hãy xem xét bạn có nhiều chủ đề làm việc trên cùng một đối tượng. Bạn không thể dự đoán kết quả mã của mình vì hành động của một luồng sẽ sửa đổi đối tượng, luồng tiếp theo sử dụng đối tượng này làm tham số sẽ nhận được dữ liệu hoàn toàn khác và không có gì đảm bảo rằng hoạt động sẽ an toàn
Bạn không thể giữ một bản sao của một đối tượng bằng cách gán nó cho một biến trước, sau đó sửa đổi các thuộc tính của đối tượng ban đầu. Các giá trị thuộc tính trong bản sao cũng sẽ thay đổi
Với các loại bất biến, chúng tôi biết rằng trạng thái của một giá trị sẽ không bị thay đổi sau khi chúng tôi tạo nó, do đó không dẫn đến logic không mong muốn trong mã của chúng tôi. Chẳng hạn, chúng tôi muốn so sánh hai chuỗi email để xác thực người dùng. Nếu một chuỗi có thể thay đổi và một phần mã của chúng tôi đã thay đổi chuỗi email bên trong một số phương thức khác, thì người dùng sẽ không thể đăng nhập
Chúng ta có thể tạo các đối tượng JavaScript bất biến không?
May mắn thay, có. JavaScript là ngôn ngữ phổ biến hỗ trợ các mô hình lập trình khác nhau, tất nhiên, có cách khắc phục hầu hết các vấn đề. JavaScript có đối tượng. chức năng đóng băng []. Gọi hàm sau khi tạo các đối tượng của bạn đánh dấu tất cả các thuộc tính của đối tượng là không thay đổi
Nếu bạn cố gán lại một giá trị thuộc tính, nó sẽ âm thầm thất bại hoặc trong trường hợp bạn đã bật chế độ nghiêm ngặt, một ngoại lệ sẽ được đưa ra. Đây là một mẫu mã;
obj4 = {name:"James"} obj5 = obj4; Object.freeze[obj4]; console.log[obj5]; // {name: "James"} obj4.name = "Daniels"; //Trying to modify the property value. Note that this won't throw an error, however, it won't change the value of the name property. console.log[obj4]; // {name: "James"} console.log[obj5]; // {name: "James"}
Facebook ra mắt thư viện có tên Immutable. js để làm việc với React. js, một front-end framework, cũng của Facebook. Thư viện này hướng đến sự bền vững dễ dàng của các đối tượng, sao chép và so sánh, lý luận đơn giản hơn và mã hóa ít phức tạp hơn để tránh lỗi của các loại có thể thay đổi trong JavaScript