封装可以被定义为对对象的内部数据表现形式和实现细节进行隐藏。通过封装可以强制实施信息隐藏。
在JavaScript中,并没有显示的声明私有成员的关键字等。所以要想实现封装/信息隐藏就需要从另外的思路出发。我们可以使用闭包的概念来创建只允许从对象内部访问的方法和属性,来达到封装的要求。
基本方式
一般来说,我们学用的有三种方法来达到封装的目的。
使用this.XXX来声明一个变量,然后再声明getXXX、setXXX等取值、赋值的方法。
使用this._XXX来声明一个变量,然后再声明getXXX、setXXX等取值、赋值的方法。
利用“函数作用域”这一个概念来做。
1. 门户大开型
var
JavaScript中的封装是面向对象编程的一个核心概念,它涉及到如何管理和保护对象内部的数据,以及如何控制对这些数据的访问。在JavaScript这种动态类型的脚本语言中,由于没有像Java那样的访问修饰符(如private、public),因此实现封装的方式相对独特。
1. **基本封装方式**
- **使用this关键字**:在构造函数中,使用`this`关键字声明的属性可以直接从对象实例外部访问,但这并不提供真正的封装。为了限制访问,通常会配合getter和setter方法,如`getIsbn()`和`setIsbn()`,来间接操作这些属性。
- **命名规范**:一种常见的实践是在私有属性前加上下划线`_`,例如`_isbn`,以此暗示它们不是公开的接口。然而,这仅是一种约定,不能阻止直接访问,所以仍不满足封装的要求。
2. **利用函数作用域**
- **封闭变量**:这是实现封装的一种更有效的方式。在构造函数内部,使用`var`声明的变量具有局部作用域,只能在该函数内部访问。这样,通过在getter和setter内部引用这些变量,可以确保外部代码无法直接修改它们。例如:
```javascript
var Book = function(newIsbn, newTitle, newAuthor) {
var isbn, title, author;
this.setIsbn = function(newIsbn) {
isbn = newIsbn;
};
this.getIsbn = function() {
return isbn;
};
// ... 其他方法
}
```
这种方式有效地隐藏了内部状态,符合封装的原则。
3. **IIFE(立即执行函数表达式)增强封装**
- **使用IIFE(Immediately Invoked Function Expression)**可以进一步强化封装,通过将构造函数的定义置于一个匿名函数内,然后立即调用该函数,可以创建一个私有的作用域。在这个作用域内声明的变量和函数无法从外部直接访问,提供了更强的封装性。例如:
```javascript
var Book = (function() {
var isbn, title, author;
return function(newIsbn, newTitle, newAuthor) {
this.setIsbn = function(newIsbn) {
isbn = newIsbn;
};
this.getIsbn = function() {
return isbn;
};
// ... 其他方法
};
})();
```
4. **模块化封装**
- 随着JavaScript模块化的发展,还可以利用ES6的`class`语法和`private`字段(仅在类内部可访问)来实现更现代的封装。不过,这个特性并非所有环境都支持,需要考虑兼容性问题。
JavaScript中实现封装主要是通过函数作用域、闭包和命名约定来达到信息隐藏的效果。尽管JavaScript没有内置的私有变量或方法,但通过巧妙的编程技巧,依然可以构建出安全且具有封装性的对象模型。在实际开发中,选择合适的方法取决于项目的具体需求和目标环境。