单例模式
又称为单体模式。保证一个类只有一个实例,并提供一个访问它的全局访问点。
第二次使用同一个类创建新对象的时候,应该得到第一次创建的对象完全相同的对象。
通过静态属性创建单例
class Person{
static instance = null; //静态属性,不会被实例继承,由类直接调用
constructor(name){
if(Person.instance){
return Person.instance;
}
Person.instance = this;
this.name = name;
}
}
通过函数创建单例
let instance;
function createInstance(...arg){
if(!instance){
instance = new Game(...arg);
}
return instance;
}
==优点:==实现代码复用性,封装良好,抽象逻辑
==缺点:==单例模式扩展性不强
工厂模式
function createPerson(name, age) {
var obj = {};
obj.name = name;
obj.age = age;
obj.writeJs = function () {
console.log(this.name + 'write js');
}
return obj;
}
var p1 = createPerson('mengzhe' , 26);
p1.writeJs();
var p2 = createPerson('iceman' , 25);
p2.writeJs();
==优点:==实现代码复用性,封装良好,抽象逻辑
==缺点:==不能识别对象的类型,全部是Object
构造函数模式
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
};
}
const scater = new Person("scater", 29, "web前端");
console.log(scater instanceof Person)// true
- 首字母大写
- 使用new创建对象
==优点:==能够识别对象
==缺点:==每次创建实例的时候都要重新创建一次方法
原型模式
原型模式适合在创建复杂对象时,对于那些需要一直在变化而导致对象结构不停地改变时,将那些比较稳定的属性与方法共用而提取的==继承==的实现。
Object.create() //ES5原生方法实现
function Person(){}
Person.prototype.name = "scater";
Person.prototype.age = 29;
Person.prototype.job = "web前端";
Person.prototype.sayName = function(){
alert(this.name);
};
const scater = new Person();
scater.sayName(); // "scater "
==优点:==可以让所有对象实例共享它所包含的属性和方法
==缺点:==如果属性中存在引用类型,修改了会互相影响
混合模式(原型模式 + 构造函数模式)
创建自定义类型的最常见方式。
构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ["Shelby", "Court"];
}
Person.prototype = {
constructor : Person,
sayName : function(){
alert(this.name);
}
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Count,Van"
alert(person2.friends); //"Shelby,Count"
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true
==优点:==每个实例都会有自己的一份实例属性的副本,但同时又共享着对方法的引用,最大限度地节省了内存。
动态原型模式
动态原型模式把所有信息都封装在了构造函数中,而通过在构造函数中初始化原型,又保持了同时使用构造函数和原型的优点。
可以通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型。
function Person(name, age, job){
//属性
this.name = name;
this.age = age;
this.job = job;
// 方法
if (typeof this.sayName != "function"){
Person.prototype.sayName = function(){
alert(this.name);
};
}
}
const scater = new Person("scater", 29, "web前端");
scater.sayName(); // "scater"