面向对象的 JavaScript
前言
学习设计模式的前置知识,JavaScript
语言本身由原型模式实现,进一步了解原型模式。
重点
- 原型模式理解
- 原型继承的实现原理
- 模拟
new
运算过程 Object.create()
的polyfill
多态
JavaScript
由于是动态型语言,天生自带多态特性
封装
封装数据
封装实现
封装设计
原型模式和基于原型继承的 JavaScript 对象系统
原型模式
在原型编程的思想中,类并不是必须的,对象未必需要从类中创建而来,一个对象是通过克隆另外一个对象所得到的。
原型模式不单单是一种设计模式,也被称为一种编程泛型。
使用克隆的原型模式
从设计模式的角度讲,原型模式是用于创建对象的一种模式,如果我们想要创建一个对象,一种方法是先指定它的类型,然后通过类来创建这个对象。原型模式选择了另外一种方式,我们不再关心心对象的具体类型,而是找到一个对象,然后通过克隆来创建一个一模一样的对象。
克隆是创建对象的手段
原型编程的一些规则
- 所有的数据都是对象
- 根对象是
Object.prototype
- 根对象是
- 要得到一个对象,不是通过实例化类,而是找到一个对象作为原型并克隆它
JavaScript
的函数既可以作为普通函数被调用,也可以作为构造器被调用new
运算过程理解如下
function Person (name) { this.name = name; }; Person.prototype.getName () { return this.name; }; // new运算过程 var objectFactory = function () { var obj = new Object(), // 从Object.prototype 上克隆一个空的对象 Constructor = [].shift.call(arguments); // 取到外部传入的构造器 obj.__proto__ = Constructor.prototype; // 指向正确的原型 __proto__ === 构造器的原型 var ret = Constructor.apply(obj, arguments); // 借用外部传入的构造器为obj设置属性 return typeof ret === 'object' ? ret : obj; // 确保构造器总会返回一个对象 }; var a = objectFactory(Person, 'Careteen'); console.log(a.name); // Careteen console.log(a.getName()); // Careteen console.log(Object.getPrototypeOf(a) === Person.prototype); // true
- 对象会记住它的原型
obj.__proto__ = Constructor.prototype;
- 如果对象无法响应某个请求,它会把这个请求委托给它自己的构造器的原型
- 原型继承实现如下
var obj = { name: 'Careteen' }; var A = function () {}; A.prototype = obj; var a = new A(); console.log(a.name); // Careteen
- 类继承一个类实现
var A = function () {}; A.prototype = { name: 'Careteen' }; var B = function () {}; B.prorotype = new A(); var b = new B(); console.log(b.name);
ES5提供了Object.create
方法,可以用来克隆对象。
某些浏览器不支持Object.create
,可如下ployfill
Object.create = Object.create || function (obj) {
var F = function () {};
F.prototype = obj;
return new F();
}