这是我参与【第四届字节青训营】笔记创作活动的第二天
JavaScript中的设计模式
1.工厂模式
工厂模式是一种常见的设计模式,广泛应用于软件工程领域,用于抽象创建特定对象的过程。在JavaScript中也提到了这种设计模式,下面用一个例子来展示这种按照特定接口创建对象的方式:
function createPerson(name,age,hobby){
let person=new Object();
person.name=name
person.age=age
person.hobby=hobby
person.setName=function(){
console.log(this.name);
}
return person
}
let person1=createPerson('ww',18,'dance')
let person2=createPerson('xx',19,'sing')
在这个例子中,createPerson函数接收三个参数,根据这几个参数构造了一个包含Person信息的对象。可以用不同的参数多次调用这个函数,每次都会包含返回三个属性和一个方法的Object类型的对象。但使用这种设计模式有一个问题就是无法判断新创建的对象是什么具体的类型。
2.构造函数模式
在ECMAscript中的构造函数是用于创建特定类型对象的。Object和Array这种的原生构造函数,运行时可以直接在运行环境中使用。但当我们想要定义自己的对象类型属性和方法时就可以采用构造函数这种模式
function Person(name,age,hobby){
this.name=name
this.age=age
this.hobby=hobby
this.setName=function(){
console.log(this.name);
}
return person
}
let person1=new Person('ww',18,'dance')
let person2=new Person('xx',19,'sing')
person1.setName()//ww
person2.setName()//xx
在这个例子中,要创建Person的实例,应使用new操作符,使用new调用构造函数时,实际执行了这几个操作:
- 在内存中创建一个新对象
- 这个新对象内部的[[prototype]]特性被赋值为构造函数的prototype属性
- 构造函数内部的this被赋值为这个新对象(this指向新对象)
- 执行构造函数内部的代码(给新对象添加属性)
- 如果构造函数返回非空对象,则返回该对象,否则返回刚创建的对象
这个例子中,person1和person2分别保存着Person的不同实例。这两个对象都有一个constructor属性指向Person,在JavaScript中constructor属性是用来标识对象类型的。准确起见,可以用instanceOf操作符来确定对象类型。
通过这个例子可以看出,通过自定义构造函数可以确保被标识为特定类型,而不仅仅是Object,Array等原生类型。但构造函数也存在问题,因为方法定义在构造函数类,所以每创建一个实例,定义的方法也会在实例中创造一遍。因为每次创造的都是不同的实例,而创造的Function实例的机制是一样的,所以没有必要定义两个不同的Function实例,所以可以用原型模式来解决
3.原型模式
在JavaScript中,每个函数都会创建一个prototype属性,这个属性指向一个对象,这个对象中包含了我们定义的函数中的属性和方法,这个对象就是通过调用构造函数创建的对象的原型。使用原型对象的好处就是,在它上面定义的属性和方法可以直接被对象实例共享。原来在构造函数中直接赋给对象实例的值,可以直接赋值给它们的原型。例子如下:
Person.prototype.name='dd'
Person.prototype.age='18'
Person.prototype.hobby='dance'
Person.prototype.sayName=function(){
console.log(name)
}
let person1=new Person()
let person2=new Person()
person1.sayName();//dd
person2.sayName();//dd
使用这种设计模式,所有属性和sayName()方法都直接添加到了Person的prototype属性指向的对象中,构造函数中并没有该属性和方法。但这样定义后,调用构造函数创建的对象的原型中也自动添加了这些方法和属性。
下面一章就来聊聊原型机制