一直对工厂模式、构造函数及原型模式的定义有些模糊,今天抽了些时间学了下工厂模式、构造函数及原型模式的区别及用途,小结一番。
一、工厂模式
// 工厂模式 function createPerson(name,age){ var o = new Object(); o.name = name; o.age = age; return o; } var person1 = createPerson('one','20'); var person2 = createPerson('two','10');
作用:工厂模式可以快速创建类似的对象
缺点:创建的对象不具有识别性,故此我们可以使用构造函来解决这个问题
二、构造函数
// 构造函数 function Person(name,age){ this.name = name; this.age = age; this.sayName = function(){ alert(this.name); } } var person = new Person('mrz','26');
实例化构造函数相比于普通的工厂模式,其多也constructor指向了Person()用以识别其他实例的构造函数。
new Person()包含了四个步聚:
①创建一个新对象
②将构造函数的作用域赋给新对象(this指向新对象)
③执行构造函数
④返回新对象
构造函数本身也可以直接执行,但是这样this就指向了window
Person('mrz','26'); //调用sayName 此时sayName已经定义到了Global window.sayName(); //mrz
缺点:构造函数每次实例都会将函数内部的属性,全部复制给新对象,内部定义的函数也是多次实例化,造成不必要的浪费,故此应该将其公用部分复用,故此原型模式可以帮忙解决这一问题。
三、原型模式
// 原型模式 function Person(){} Person.prototype = { name : 'mrz', age : '26', sayName : function(){ alert(this.name); } } var person = new Person();
new 原型,新对象的constructor将指向Person.prototype,获取Person.prototype上的属性,同时其本身也添加本身的实例属性,来获得本身实例所需的属性值。
// 原型模式 function Person(){} Person.prototype = { name : 'mrz', age : '26', sayName : function(){ alert(this.name); } } var person = new Person(); person.name = 'marz';
原型模式也有一个比较大的问题,那就引用类型的数值,会被共用,一个对象操作会改变其他对象。
// 原型模式 function Person(){} Person.prototype = { name : 'mrz', age : '26', friend : ['one','two'], sayName : function(){ alert(this.name); } } var person1 = new Person(); var person2 = new Person(); person1.friend.push('three'); console.log(person2.friend); //["one", "two", "three"]
解决这个问题,可以让构造函数+原型模式结合解决。
// 构造函数+原型模式 function Person(){ this.name = 'mrz'; this.age = '26'; this.friend = ['one','two']; } Person.prototype = { sayName : function(){ alert(this.name); } } var person1 = new Person(); var person2 = new Person(); person1.friend.push('three'); console.log(person1.friend); // ['one','two','three'] console.log(person2.friend); // ['one','two']