面向对象的程序设计--创建对象
1、工厂模式
涵义:抽象了具体创建对象的过程,用函数来封装以特定接口创建对象的细节。
优点:解决了创建多个相似对象的问题。
缺点:没有解决对象识别的问题。
function createPerson(name, age, job) {
let o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function() {
alert(this.name);
};
return o;
}
let person1 = createPerson("Vince", 26, "FE");
let person2 = createPerson("Yisimo", 18, 'Poet');
console.log('person1', person1) //{name: "Vince", age: 26, job: "FE", sayName: ƒ}
console.log('person2', person2) //{name: "Yisimo", age: 18, job: "Poet", sayName: ƒ}
2、构造函数模式
涵义:创建自定义的构造函数,从而定义自定义对象的属性和方法。
优点:解决了对象识别的问题,可以将它的实例标识为一种特定的类型。
缺点:每个方法都要在每个实例上重新创建一遍,会导致不同的作用域链和标识符解析。
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() {
alert(this.name);
}
}
let person3 = new Person("Vince", 25, "FE");
let person4 = new Person("Yisimo", 20, "Poet");
console.log('person3', person3) // Person {name: "Vince", age: 25, job: "FE", sayName: ƒ}
console.log('person4', person4) // Person {name: "Yisimo", age: 20, job: "Poet", sayName: ƒ}
3、原型模式
涵义:不在构造函数中定义实例的信息,而是将这些信息直接添加到原型对象中。
优点:可以让所有对象实例共享原型对象包含的属性和方法。
缺点:所有对象实例共享一个数组,实例没有属于自己的全部属性;省略了为构造函数传递初始化参数的环节,所有实例在默认情况下都取得相同的属性值。
function PersonProto() {}
PersonProto.prototype = {
constructor: PersonProto,
name: 'Vince',
age: '26',
job: 'FE',
sayName: function() {
alert(this.name);
}
};
let person5 = new PersonProto();
let person6 = new PersonProto();
person6.name = "Yisimo";
person6.age = 20;
console.log(person5.name, person5.age) // Vince 26
console.log(person6.name, person6.age) // Yisimo 20
4、组合使用构造函数模式和原型模式
涵义:混成模式,构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性。目前使用最广泛、认同度最高的一种模式。
优点:每个实例都有自己的一份实例属性的副本,同时又共享着对方法的引用,最大限度地节省了内存;还支持向构造函数传参。
function PersonHybrid(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.friends = ["John", "Mike"];
}
PersonHybrid.prototype = {
constructor: PersonHybrid,
sayName: function() {
alert(this.name);
}
}
let person7 = new PersonHybrid("Vince", 22, "FE");
let person8 = new PersonHybrid("Yisimo", 20, "Poet");
person7.friends.push("Van");
console.log(person7.friends); // ["John", "Mike", "Van"]
console.log(person8.friends); // ["John", "Mike"]
console.log(person7.friends === person8.friends); // false
console.log(person7.sayName === person8.sayName); // true
5、动态原型模式
涵义:把所有信息都封装在构造函数中,而通过在构造函数中初始化原型(仅在必要的情况下),又保持了同时使用构造函数和原型的特点。
function PersonDynamic(name, age, job) {
// 属性
this.name = name;
this.age = age;
this.job = job;
// 方法
if (typeof this.sayName != 'function') {
PersonDynamic.prototype.sayName = function() {
alert(this.name);
}
}
}
let person9 = new PersonDynamic("Vince", 23, "FE");
person9.sayName(); // Vince
6、寄生构造函数模式
涵义:基本思想是创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新创建的对象。
备注:除了使用new操作符,并把使用的包装函数叫做构造函数之外,该模式与工厂模式其实是一模一样的。
function PersonParasitic(name, age, job) {
let o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function() {
alert(this.name);
}
return o;
}
let person10 = new PersonParasitic("Vince", 21, "FE");
person10.sayName(); // Vince
7、稳妥构造函数模式
涵义:遵循与寄生构造函数类似的模式,但有两点不同:一是新创建对象的实例方法不引用this;二是不使用new操作符调用构造函数。
备注:适合在安全环境中,或者在防止数据被其他应用程序改动时使用。
function PersonParasitic(name, age, job) {
let o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function() {
alert(name);
}
return o;
}
let person11 = new PersonParasitic("Vince", 21, "FE");
person11.sayName(); // Vince 除了使用sayName()方法外,没有别的方式可以访问其数据成员。