厘清面向对象四种模式:工厂模式、构造函数模式、原型模式、混合模式
面向对象是一种方法,用来封装功能,方便日后使用,避免大量的重复工作
一、工厂模式
(一)实现方法:在函数内创建一个对象并给对象赋予属性及方法,最终将对象返回。
1 function cPerson(name,sex,age){ 2 var o = new Object(); 3 o.name = name; 4 o.sex = sex; 5 o.age = age; 6 o.show = function(){ 7 console.log(this.name,this.age,this.sex); 8 } 9 return o; 10 } 11 var p1 = cPerson('瀚哲,'男','18'); 12 p1.show(); 13 var p2 = cPerson('丑小鸭','女','18'); 14 p2.show();
(二)工厂方式的问题:使用工厂模式能够创建一个包含所有信息的对象,可以无数次的调用的这个函数。虽然其解决了创建多个相似对象的问题,但却没有解决对象识别的问题(即如何得知一个对象的来源和类型),因此出现了构造函数。
二、构造函数模式
(一)实现方法:
1 function CPerson(name,sex,age) { 2 this.name = name; 3 this.sex = sex; 4 this.age = age; 5 this.show = function () { 6 console.log(this.name, this.age, this.sex); 7 } 8 } 9 var p1 = new CPerson('瀚哲 ','男','18'); 10 p1.show(); 11 var p2 = new CPerson('丑小鸭','女','14'); 12 p2.show();
(二)构造函数与工厂模式的不同之处:
1.构造函数首字母大写
2.没有显式地创建对象
3.将属性和方法赋值给了 this 对象
4.没有return语句
(三)以这种方式来调用构造函数会大致经历以下几个步骤:
1.创建一个新的对象
2.将构造函数的作用域赋值给这个对象(因此this就指向了这个对象)
3.执行构造函数中的代码(即给新对象添加属性和方法的过程)
4.返回对象
(四)构造函数的问题:
1.使用构造函数的最大的问题在于每次创建实例的时候都要重新创建一次方法(理论上每次创建对象的时候对象的属性均不同,而对象的方法是相同的),然而创建两次完全相同的方法是没有必要的,因此,我们可以将函数移到对象外面;
2.在全局作用域中定义了许多仅供特定对象使用的方法,浪费空间,显然失去了面向对象封装性了,因此可以通过原型来解决此问题。
三、原型模式
(一)实现方法: 创建的每个函数都有prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。使用原型对象的好处就是可以让所有对象实例共享它所包含的属性及方法。
1 function CPerson(){ 2 } 3 CPerson.prototype.name='瀚哲'; 4 CPerson.prototype.sex='男'; 5 CPerson.prototype.age=100; 6 CPerson.prototype.show=function(){ 7 console.log(this.name, this.age, this.sex); 8 } 9 var p1 = new CPerson(); 10 p1.show(); //瀚哲 18 男 11 var p2 = new CPerson(); 12 p2.show();//瀚哲 18 男 13 console.log(p1.show == p2.show) //打印值为true
(二)原型模式的问题:
1.它省略了构造函数传递初始化参数这一环节,结果所有实例在默认情况下都取得了相同的属性值,这样非常不方便;
2.原型模式的最大问题在于共享的本性所导致,由于共享,因此一个实例修改了引用,另一个也随之更改了引用。因此我们通常不单独使用原型,而是结合原型模式与构造函数模式。
四、混合模式
1 function CPerson(name,sex,age) { 2 this.name = name; 3 this.sex = sex; 4 this.age = age; 5 this.show(); 6 } 7 CPerson.prototype.show = function(){ 8 alert(this.name + this.sex + this.age) 9 } 10 var CPerson1 = new CPerson("甄瀚哲","男",18); 11 var CPerson2 = new CPerson("丑小鸭","女",18); 12 CPerson1.show(); 13 CPerson2.show();
混合模式中构造函数模式用于定义实例属性,而原型模式用于定义方法和共享属性。每个实例都会有自己的一份实例属性,但同时又共享着方法,最大限度的节省了内存。另外这种模式还支持传递初始参数。