JavaScript 类的封装

参考:
js 如何创建类(封装)
Class 的基本语法
《JavaScript 设计模式》

JavaScript 类的封装

JavaScript 中,类的实现是基于原型继承机制的。如果两个实例都从同一个原型对象上继承了属性,我们说它们是同一个类的实例。

如果两个对象继承自同一个原型,往往意味着它们是由同一个构造函数创建并初始化的。

类的创建

JavaScript 中创建一个类很容易,声明一个函数保存在一个变量中,在这个函数内部使用this 添加属性或者方法。

也可以通过在类的原型对象上添加属性和方法。

⁉️ 通过 prototypethis 添加属性和方法有什么区别?通过 this 是在当前对手上添加的,每次对象被创建时这些方法和属性都会被重复创建;而通过 prototype 继承的方法不是对象自身的,所以当使用这些方法和属性时,会通过 prototype 一级一级想上查找(原型链),所有不会被重复创建(但是原型上的属性被修改是,所有继承该原型的对象都会被影响)。

⁉️ 什么是 constructor ?这是一个属性,当创建一个函数或对象时都会为期创建一个原型对象 prototype, 在 prototype 对象中又会创建一个 constructor 属性,那么 constructor 属性指向的就是拥有整个原型对象的函数或者对象。

属性和方法的封装

利用 JavaScript 的函数级作用域,声明在函数内部的变量以及方法在外界是访问不到的,通过此特性即可创建私有变量和私有方法。

思考 new 运算符原理,通过 new 实例化对象时,构造函数执行,this 执行新创建的对象。

类通过 prototype 创建的属性或者方法在类的实例对象是可以通过 this 访问的。

再进一步,利用闭包进行封装

闭包是有权访问另一个函数作用域中变量的函数,即在一个函数内部创建另一个函数。我们将这个闭包作为创建对象的构造函数,在闭包内部返回一个完整的类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var Book1 = (function() {
var bookNum = 0
function checkBook(name) {}

function _book(newID, newName, newPrice) {
var name, price
function checkID(id) {}

this.getName = function() {
name
}
}

//直接构建原型
_book.prototype = {
isJSBook: true
}

// 记得要返回该对象,否则会 “is not a constructor”
return _book
})()

var book1 = new Book1()

创建对象的安全模式

当忘记写 new 运算符时,是对象的直接复制,对象内部的 this 指向的是全局对象window,使用 instanceof 运算符判断当前 this,在使用闭包的封装中,是不会有整个问题的,其属性和方法都被限定在函数内部的作用域中。