面向对象编程(Object-Oriented Programming)是基于对象的一种编程范式(paradigm)。其有三个广为人知的特性,封装(Encapsulation)、继承(Inheritance)和多态(Polymorphism),让编程更灵活、可维护。常见的面向对象编程方式都是基于类(class)的,在 C++、Java 等高级语言中都以类的形式得到实现。
在 JavaScript(以下简称 JS)是基于对象的弱类型语言,并无类的概念,但其提供了原型机制,可用来支持面向对象编程。下面分别用 JS 实现 OOP 三大特性。
封装
之前我一直以为封装指的是方法与数据能放在一起(类),但一看维基百科才得知,封装是一种限制外部直接访问对象内部数据与方法的语言机制。在 C++ 中,封装就是通过 public
、private
(和 protected
) 来实现的。
JS 中并没有提供该机制,但可以借助闭包来实现私有变量与方法。
1 2 3 4 5 6 7 8 9 10 11
| function foo () { let name = 'Hankey' this.getName = () => name; this.setName = n => { name = n }; } let fool = new foo() fool.name fool.getName() fool.setName('Mr.Hankey') fool.getName()
|
继承
JS 没有类这个概念,但却提供了原型链(Prototype Chain)机制,使得继承成为可能。关于原型这里且不细谈。(BTW,Self 是第一个实现原型的编程语言)
虽说都是使用原型,但不同的使用方法会形成各样的继承方式。目前最为完善的似乎就是组合寄生式继承了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function papa (name) { this.name = name } papa.prototype.toString = function _toString () { console.log('Papa is ' + this.name + '!') } function baby (name, gender) { papa.call(this, name) this.gender = gender } baby.prototype = Object.create(papa.prototype) baby.prototype.constructor = baby baby.prototype.toString2 = function _toString2 () { console.log('Baby named ' + this.name + ', is a ' + this.gender + '.'); } var eleven = new baby('11', 'girl') eleven.toString() eleven.toString2()
|
Object.create(obj, [properties])
在做的就是创建一个原型为 obj
的对象。它实际上做的事情基本如下:
1 2 3 4 5
| function create (obj) { function F () {} F.prototype = obj return new F() }
|
多态
参考资料
- Object-oriented programming
- Encapsulation
- Inheritance
- Prototype-based programming