1、工厂模式
首先来看看常用的两种创建对象的方式:
1、字面量创建
var person = {
name:'zhansgan',
age:18,
sayName:function() {
console.log(this.name);
}
}
2、构造函数
// 构造函数
var person = new Object()
person.name = 'zhansgan'
person.age = 13
person.sayName = function() {
console.log(this.name);
}
3、工厂模模式创建
// 将创建对象的代码封装在一个函数中
function createPerson(name,age,gender) {
var person = new Object()
person.name = name;
person.age = age;
person.gender = gender;
person.sayName = function () {
console.log(this.name);
}
return person;
}
// 利用工厂函数来创建对象
var person1 = createPerson('zhangsan',18,'male')
var person2 = createPerson('lisi',16,'female')
console.log(person1 instanceof createPerson);//false
工厂模型优点是:可以批量的创建对象,只要往函数里面传递不同的参数就能创建出不同的实例
工厂模式缺点是:无法进行分类,创建的实例指向的原型都是Object,就相当于你创建一个人使用的Object,创建的狗也是使用Object。且实例调用的方法不是同一个方法,也就是说每次创建一个实例,同时也会创建出实例里面的方法,造成内存空间的浪费和代码冗余。
2、自定义构造函数模型
自定义构造的出现是为了解决无法分类的问题。
使用自定义的构造函数可以定义出不同的种类。
function Person(name,age,gender) {
this.name = name;
this.age = age;
this.gender = gender;
this.sayName = function () {
console.log(this.name);
}
}
// 创建 p1、p2实例
var p1 = new Person('zhangsan',15,'male')
var p2 = new Person('lisi',19,'female')
p2.sayName()
p1.sayName()
要创建Person的实例,应该使用new操作符。new在js中做了以下的事情:
1、创建了一个实例对象 Person
2、this指向Person实例对象 this---p1,p2
3、执行函数
4、返回Person实例对象
构造函数与普通函数唯一的区别就是调用方式不同。
但是仍然存在每次创建一个对象实例,其定义的方法也会在每个实例上再创建一次!!!
还是存在内存空间的浪费!!
解决方法:把在构造函数内部定义的方法移到函数外部去,也就是将方法定义在全局作用域中
var Person = function (name , age , gender) {
this.name = name;
this.age = age;
this.gender = gender;
this.sayName = sayName;
}
function sayName() {
console.log(this.name);
}
这样解决了创建实例就创建方法的问题
但是,新的问题又出现了
在构造函数外部定义方法,该方法就是处于全局作用域中
随着方法的不断增多,会扰乱全局作用域,而且放在全局作用域中其他的实例也能调用!!
但是我并不想给其他对象调用!!
3、原型模型
解决方法:将方法定义到原型模式上,对象可以调用原型模式上的方法
function Person(params) {}
Person.prototype.name = 'zhangsan'
Person.prototype.age = 18
Person.prototype.gender = 'male'
Person.prototype.sayName = function () {
console.log(this.name);
}
var person1 = new Person()
person1.sayName()
var person2 = new Person()
person2.sayName()
// 验证实例1和实例2所调用的方法是否是同一个
console.log(person1.sayName === person2.sayName);
这样就解决了方法放在全局作用域的问题了,但是原型上的所有属性和方法是在实例之间都是共享的,但是总有一些方法,是我们不想共享的,那么怎么办??
4、组合模式
解决方法:使用构造函数和原型模式的组合模式
构造函数的问题:方法不能共享
原型模型的问题:全部方法共享
那么我们就把想要共享的方法放在原型模型中,不想共享的方法放在构造函数中不就行了!!
//构造函数创建
function Person(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
this.firends = ['zhangsan', 'lisi'];
}
//原型创建
Person.prototype = {
//constructor: Person,
sayName: function () {
console.log(this.name);
}
};
//改变构造函数的指向
Object.defineProperty(Person.prototype,'constructor',{
enumerable:fasle
value:Person
})
var p1 = new Person('larry', 44, 'male');
var p2 = new Person('terry', 39, 'male');
p1.firends.push('robin');
console.log(p1.firends); // [ 'zhangsan', 'lisi', 'robin' ]
console.log(p2.firends); // [ 'zhangsan', 'lisi' ]
console.log(p1.firends === p2.firends); // false
console.log(p1.sayName === p2.sayName); // true