工厂模式与构造函数模式

简单工厂模式

以Object构造函数或字面量的方式创建对象有着重复性,会产生大量重复代码的缺陷,由此,便出现了工厂模式。

function createObj (name,age) {

var obj = new Object();

obj.name = name;
obj.age = age;

return obj;
}

var obj1 = createObj("小明",66);
var obj2 = createObj("小白",13);

console.log(obj1.name) //小明
console.log(obj2.name) //小白

工厂模式的缺陷
由于新建的所有对象都是Object的实例。所以出现了对象的识别问题

  console.log(obj1 instanceof Object) //true
    console.log(obj2 instanceof Object) //true

为了解决上述问题,又出现了构造函数模式

function CreateObj (name,age) {
this.name = name;
this.age = age;
this.sayName = function () {
}
}

var obj1 = new CreateObj('小白',19);
var obj2 = new CreateObj('小明',10);

console.log(obj1.name)//小白
console.log(obj2.name)//小明

可以看到工厂模式与构造函数的区别
没有在函数内部新建Object实例 — var obj = new Object();
把属性和方法都添加到了this上。
最后也没有返回值。

注意,函数名的第一个字母是大写,当然没有也可以,但这样做是为了区分构造函数与普通函数的区别,按照惯例是要加上的。事实上,构造函数和普通函数一样,没有什么区别。而当调用函数的时候如果使用了new操作符,那么这个普通的函数就成了一个构造函数。

当使用了new操作符对函数进行调用的时候,后台会新建一个对象,将构造函数作用域赋给新的对象,所以this指针就指向了这个对象。最后是执行构造函数里的代码,这里是给新建的对象中添加了两个属性与方法。

此外,我们可以对这些实例化对象进行识别了。




 function CreateObj1 (name,age) {
this.name = name;
this.age = age;
this.sayName = function () {
}
}

function CreateObj2 (name,age) {
this.name = name;
this.age = age;
this.sayName = function () {
}
}

var obj1 = new CreateObj1("小明",11);
var obj2 = new CreateObj2("小红",11);

console.log(obj1.constructor) //CreateObj1  obj1实例的构造函数是CreateObj1
console.log(obj2.constructor) //CreateObj2 obj2实例的构造函数是CreateObj2

console.log(obj1 instanceof CreateObj1) //true obj1从属于CreateObj1
console.log(obj2 instanceof CreateObj2) //true obj2从属于CreateObj2
console.log(obj1 instanceof CreateObj2) //false obj1不从属于CreateObj2

由此解决了对象识别的问题,我们可以知道这些实例对象都从属于谁,而不像工厂模式一样,所以的的实例对象都只是从属于Object。但其实所以的对象都是从属于Object的。

console.log(obj1 instanceof Object) //true 
console.log(obj2 instanceof Object) //true 
console.log(obj1.__proto__.__proto__ === Object.prototype) //true

但构造函数模式仍存在一些问题,即每个方法都会被重新创建一遍。

function CreateObj1 (name,age) {
this.sayName = function () {
}
}

以上函内在sayName属性上定义了一个方法。而定义一个方法,就会生成一个新的对象。(函数也是对象)
如同 : var sayName = new Function(…)
这样,随着构造函数的每一次调用,就会新建出越来越多的相同的方法,而这些方法的功能都是相同的,浪费了空间。

function CreateObj1 () {
this.sayName = function () {
}
}

var obj1 = new CreateObj1();
var obj2 = new CreateObj1();

console.log(obj1.sayName == obj2.sayName) //false 

通过地址的比较可以发现,不同实例之间的方法的引用地址是不同的。

如果说要避免重复创建方法的问题,可以这样做:

function CreateObj1 () {
this.sayName = sayName;
}

function sayName () {
console.log(1)
}

var obj1 = new CreateObj1();
var obj2 = new CreateObj1();

console.log(obj1.sayName == obj2.sayName)//true

我们把函数的定义放到构造函数的外边,然后在构造函数里保存函数的引用地址。从而避免了重复定义函数的问题。
但这种方案存在很多缺陷,并没有被人们所用,缺少封装性,污染全局。解决的方式是通过原型模式来解决。

你可能感兴趣的:(工厂模式与构造函数模式)