面向对象的设计思想是语言无关的。但是在实现上JavaScript和其他语言还是有些区别的。
对象的构造:
- 字面量 可以用JSON风格直接构造一个对象,这是一种非常直接和简洁的对象创建方式。
1 2 3 4 5 6 7 |
|
构造函数 和其他面向对象语言类似,我们可以使用new关键字加构造函数的方式来创建一个对象,在
new A
的时候JavaScript引擎做了下面几件事情:- 创建一个新的对象
- 将对象的contructor属性设置为A
- 将A.prototype设置为新对象的原型
- 以新对象为上下文(context)执行A
Object.create 这是ECMAScript 5里面提供的一个新方法,通过这个方法我们可以直接指定对象的原型。甚至通过
Object.create(null)
我们可以创建一个没有原型的“干净”对象
面向对象的三大特性:
- 封装 和其他语言不同的是,JavaScript里对象没有私有属性的概念,很多时候我们约定以下划线开头的属性为私有的,但这只是一个“君子协议”。如果实在要模拟私有属性,我们可以通过function来构造一个沙箱,沙箱里的局部变量是私有的,外部不能访问,通过function的返回值来暴露接口给外面调用
1 2 3 4 5 6 7 8 9 10 11 12 |
|
- 继承 JavaScript的原生语法是不支持继承的,但是其原型链的设计可以很好的支持继承。具体的实现方法有很多种,在这儿不一一列举了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
- 多态 这个没什么好说的,对象可以覆盖父类的属性和方法,因为JavaScript是顺着原型链往上查找属性和方法,直到找到为止。
鸭子类型
作为一门动态语言,对象类型除了可以通过原型链来描述,还可以通过一个简单的对象来表示,即所谓的“鸭子类型”————只要看起来像鸭子,就是鸭子。这种方式可以避免构造过于复杂的原型链。我们可以将常用的功能定义为mixin,需要的话直接拿来用即可。
几个重要的属性:
- obj.constructor: 指向对象的构造函数,这个属性可以被修改,但是不能通过修改该属性真正改变原型链
1 2 3 4 5 6 7 8 |
|
constructor.prototype: JavaScript里function本身也是一种特殊的对象,它包含一个属性prototype指向另一个对象,用该函数作为构造函数生成的对象就以prototype指向的对象作为原型
obj.__proto__: 在标准浏览器上对象有一个__proto__属性指向对象的原型,其等价于
obj.constructor.prototype
(如果obj.constructor
没有被篡改)