Javascript 简明教程
JavaScript - Encapsulation
What is Encapsulation?
JavaScript 中的封装是一种通过捆绑相关属性和方法到单个命名空间下,来保持这些属性和方法的私有性。它可以是函数、类或对象。在 JavaScript 中,可以使用闭包、类及访问器和设置器实现封装。
Encapsulation in JavaScript is a way to keep the related properties and methods under a single namespace by bundling them. It can be a function, a class or an object. In JavaScript, the encapsulation can be implemented using closures, classes and getters and setters.
封装是面向对象编程语言中的一个基本概念,连同继承和多态性。JavaScript 是一种面向对象的编程语言。
Encapsulation is a fundamental concept in Object-oriented programming languages, along with inheritance and polymorphism. JavaScript is an object oriented programming language.
它用于隐藏数据,避免外界访问,仅向需要的数据提供访问权限,从而提高数据的完整性和安全性。
It is used to hide the data from the outside world and give access to required data only to improve the integrity and security of the data.
What is the need for encapsulation?
让我们通过以下示例讨论在 JavaScript 中封装的必要性。
Let’s discuss the need for encapsulation in JavaScript via the following example.
例如,你在代码中定义了以下对象。
For example, you have defined the below object in your code.
const car = {
Brand: "Honda city",
model: "sx",
year: 2016,
}
如下所示,任何人都可以访问 car 对象的属性。
Anyone can access the properties of the car object, as shown below.
car.Brand
此外,如下所示,任何人都可以更改 car 对象的任何属性的值。
Also, anyone can change the value of any property of the car object, as shown below.
car.Brand = true;
此处,Brand 属性的值从字符串更改为布尔。因此,需要保护对象的原始数据,并限制外部世界对数据的访问。
Here, the value of the Brand property is changed to the boolean from the string. So, it is required to secure the original data of the object and give limited access to the data to the outside world.
在这种情况下,封装的概念进入了画面。
In this situation, the concept of encapsulation comes into the picture.
Different Ways to Achieve Encapsulation in JavaScript
有三种不同的方法来实现封装。
There are three different ways to achieve encapsulation.
-
Using the function closures
-
Using the ES6 classes
-
Using the Getters and Setters
此处,我们将逐一学习每种实现封装的方法。
Here, we will learn each approach for achieving encapsulation one by one.
Achieving Encapsulation Using the Function Closures
JavaScript 函数闭包是一个允许内部函数访问外部函数中定义的变量的概念,即使在执行了外部函数之后也是如此。在外部函数中定义的变量不能在其功能范围之外访问,但可以使用内部范围访问。
A JavaScript function closure is a concept allowing the inner function to access the variable defined in the outer function even after the outer function is executed. The variables defined in the outer function can’t be accessed outside its functional scope but can be accessed using the inner scope.
Example
在以下代码中,shoppingCart() 函数是一个外部函数,包含变量和函数。外部函数有它自己的私有范围。
In the below code, shoppingCart() function is an outer function that contains the variables and function. The outer function has its private scope.
carItems[] 数组用于存储购物车的物品。
The carItems[] array is used to store the shopping cart’s items.
add() 函数可以访问 carItems[] 数组并添加项目。
The add() function can access the carItems[] array and add items.
remove() 函数检查 cartItems[] 是否包含需要删除的物品。如果包含,则删除该物品。否则,它会打印一条消息,表明您无法删除该物品。
The remove() function checks whether the cartItems[] contains the items you need to remove. If yes, it removes the item. Otherwise, it prints the message that you can’t remove the item.
shoppingCart() 函数返回包含 add() 和 remove() 函数的对象。
The shoppingCart() function returns the object containing the add() and remove() functions.
在创建 shoppingCart() 函数的新实例之后,您可以使用 add() 和 remove() 函数来操作购物车数据。
After creating a new instance of the shoppingCart() function, you can use the add() and remove() functions to manipulate the shopping cart data.
<html>
<body>
<p id = "output"> </p>
<script>
let output = document.getElementById("output");
function shoppingCart() {
const cartItems = [];
function add(item) {
cartItems.push(item);
output.innerHTML += `${item.name} added to the cart. <br>`;
}
function remove(itemName) {
const index = cartItems.findIndex(item => item.name === itemName);
if (index !== -1) {
const removedItem = cartItems.splice(index, 1)[0];
output.innerHTML += `${removedItem.name} removed from the cart. <br>`;
} else {
output.innerHTML += `Item ${itemName} not found in the cart. <br>`;
}
}
return {
add,
remove,
};
}
// Defining items
const item1 = { name: 'Car', price: 1000000 };
const item2 = { name: 'Bike', price: 100000 };
// Create a new Shopping cart
const cart = shoppingCart();
// Adding items to the cart
cart.add(item1);
cart.add(item2);
// Remove bike from the cart
cart.remove('Bike');
</script>
</body>
</html>
Car added to the cart.
Bike added to the cart.
Bike removed from the cart.
通过这种方式,没有人可以直接访问和修改 cartItem[] 数组。
In this way, no one can directly access and modify the cartItems[] array.
Achieving Encapsulation Using ES6 Classes and Private Variables
在 JavaScript 中,您可以使用类和私有变量来实现封装。
In JavaScript, you can use classes and private variables to achieve the encapsulation.
Private Variables (Fields) in JavaScript
要定义私有类变量,您可以在变量名前面写“#”符号。例如,“name”是以下代码中的私有变量。
To define the private class variables, you can write a variable name followed by the ‘#’ sign. For example, 'name' is a private variable in the below code.
class car {
#name= "TATA";
}
如果您尝试通过类的实例访问 name,它将给您一个错误,指出类外部无法访问私有字段。
If you try to access the name by the instance of the class, it will give you an error that private fields can’t be accessed outside the class.
要实现封装,可以在类中定义私有变量,并使用不同的方法授予它们对外部世界的访问。
To achieve encapsulation, you can define the private variables in the class and give them access to the outside world using different methods.
Example
在下方的示例中,我们定义了汽车类。
In the example below, we have defined the car class.
汽车类包含 "品牌"、"名称" 和 "英里数" 私有变量。
The car class contains the 'brand', 'name', and 'milage' private variables.
定义 getMilage() 方法可返回汽车的英里数, 而 setMilage() 方法用来设置汽车英里数。
The getMilage() method is defined to return the milage of the car, and the setMilage() method is used to set the milage of the method.
我们创建了汽车类的对象,并用方法访问和修改私有字段。如果你试图访问类的私有字段,代码将抛出一个错误。
We created the car class’s object and used the method to access and modify the private fields. If you try to access the private field of the class, the code will throw an error.
你也可以定义类中的更多方法来访问和修改其他私有字段。
You can also define more methods in the class to access and modify other private fields.
<html>
<body>
<div id = "output1">The car mileage is: </div>
<div id = "output2">After updating the car mileage is: </div>
<script>
class Car {
#brand = "TATA"; // Private field
#name = "Nexon"; // Private field
#milage = 16; // Private field
getMilage() {
return this.#milage; // Accessing private field
}
setMilage(milage) {
this.#milage = milage; // Modifying private field
}
}
let carobj = new Car();
document.getElementById("output1").innerHTML += carobj.getMilage();
carobj.setMilage(20);
document.getElementById("output2").innerHTML += carobj.getMilage();
// carobj.#milage); will throw an error.
</script>
</body>
</html>
The car mileage is: 16
After updating the car mileage is: 20
Achieving Encapsulation Using the Getters and Setters
JavaScript 的 getter 和 setter 可以分别使用 get 和 set 关键字定义。getter 用于获取类属性,而 setter 用于更新类属性。
The JavaScript getters and setters can be defined using the get and set keywords, respectively. The getters are used to get the class properties, and setters are used to update the class properties.
它们和类方法非常相似,但使用 get/set 关键字后跟方法名定义。
They are very similar to the class methods but defined using the get/set keyword followed by the method name.
Example
在下面的示例中,我们定义了 User 类,其中包含三个私有字段,分别为用户名、密码和 isLoggedIn。
In the example below, we have defined the User class containing the three private fields named username, password, and isLoggedIn.
定义了名为 username 的 getter 和 setter 用于获取和设置用户名。在这里,你可以观察到 getter 和 setter 方法的名称是相同的。
The getters and setters named username are defined to get and set user names. Here, you can observe that name of the getters and setters method is the same.
之后,我们创建一个类的对象,并将 getter 和 setter 作为属性用于访问和更新类的 username 字段。
After that, we create an object of the class and use the getters and setters as the property to access and update the username field of the class.
你也可以为其他类字段创建 getter 和 setter。
You may also create getters and setters for the other class fields.
<html>
<body>
<div id = "output1">The initial username is: </div>
<div id = "output2">The new username is: </div>
<script>
class User {
#username = "Bob";
#password = "12345678";
#isLoggedIn = false;
get username() {
return this.#username;
}
set username(user) {
this.#username = user;
}
}
const user = new User();
document.getElementById("output1").innerHTML += user.username;
user.username = "Alice";
document.getElementById("output2").innerHTML += user.username;
</script>
</body>
</html>
The initial username is: Bob
The new username is: Alice
从上述所有内容,你可以理解封装使变量变为私有的,并限制其对外部世界的访问。
From the above all, you can understand that encapsulation is making variable privates and restricting its access to the outside world.
Benefits of Encapsulation in JavaScript
在此,我们列出 JavaScript 中封装的一些好处 −
Here, we have listed some benefits of encapsulation in JavaScript −
-
Data protection − The encapsulation allows you to control the access of the class data by making them private. You can expose the required data and methods only. So, no one can modify the data by mistake. Also, you can validate the data while updating them. If new data is not valid, you can throw an error.
-
Code reusability − The class is a template for the object, and you can reuse it to create objects with different data.
-
Code Maintenance − The encapsulation makes it easy to maintain the code as each object is independent, and if you make changes to one object, it doesn’t affect the other code.