直接引用JavaScript高级程序设计里的,因为里面已经写的很好了,这里只是自己的一个梳理笔记
字面量与new Object()
var a = {}
var b = new Object()
两种方式等价
适合场景:创建属性不相同的单个对象,字面量是new Object()的简写
缺陷:使用同一个接口创建很多对象(属性相同的),会产生大量的重复代码
工厂模式
function createPerson(name, age, job) {
var o = new Object()
o.name = name
o.age = age
o.job = job
o.sayName = function() {
alert(this.name)
}
return o
}
var person = createPerson('Nicholas', 29, 'Software Engineer')
适合场景:重复创建多个相同属性的独立对象,工厂模式解决了创建多个相似对象
缺陷:对象类型无法识别,因为实例全部指向一个原型(Object.prototype)
构造函数模式
function Person(name, age, job) {
this.name = name
this.age = age
this.job = job
this.seyName = function() {
alert(this.name)
}
}
var person = new Person('Nicholas', 29, 'Software Engineer')
适合场景:与工厂模式很类似创建多个相似对象,不过解决了对象类型识别的问题,alert(person1 instanceof Person) // true
缺陷:每次调用构造函数,实例都会重新创建一遍方法,方法都是每个实例独有的
原型模式
function Person(){
}
Person.prototype.name = "Nicholas"
Person.prototype.age = 29
Person.prototype.job = "Software Engineer"
Person.prototype.sayName = function(){
alert(this.name);
}
var person1 = new Person()
person1.sayName() //"Nicholas"
var person2 = new Person()
person2.sayName(); //"Nicholas"
适合场景:方法不用重复创建了,所有实例共享属性和方法
缺陷:省略了为构造函数传递初始化参数,所有实例共享属性和方法(优点也是缺点)
原型模式的简写
function Person(){
}
Person.prototype = {
name : "Nicholas",
age : 29,
job: "Software Engineer",
sayName : function () {
alert(this.name);
}
}
适合场景: 同上,另外封装的好看点了
缺陷:同上,另外constructor丢失了,如果prototype是在实例化之后被覆盖的,实例访问属性会找不到
组合模式,构造函数+原型
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")
适合场景:实例属性各自属于实例本身,方法共享不会重复创建,广泛、认同的模式
缺陷:暂时没看到
动态原型模式
function Person(name, age, job) {
this.name = name
this.age = age
this.job
if(typeof this.seyName != 'function') {
Person.prototype.seyName = function() {
alert(this.name)
}
}
}
var person = new Person("Nicholas", 29, "Software Engineer")
person.seyName()
适合场景:那些想把构造函数和原型写到一起的,这里只在 sayName()方法不存在的情况下,才会将它添加到原型中。这段代码只会在初次调用构造函数时才会执行。此后,原型已经完成初始化,不需要再做什么修改了。
缺陷:这里的prototype不能写成字面量形式直接覆盖,在创建实例new的时候构造函数的prototype会赋值给实例的__proto__, new Person()的同时等于调用了Person函数,就会执行if语句,如果这个时候直接字面量覆盖Person.prototype,实例的原型的指向并没更改,调用person.seyName还是会去原来的原型对象上找,找不到肯定就报错了
寄生构造函数模式
fubction Person(name, age, job) {
var o = new Object()
o.name = name
o.age = age
o.job = job
o.sayName = function() {
alert(this.name)
}
return o
}
var friend = new Person("Nicholas", 29, "Software Engineer")
friend.sayName() //"Nicholas"
适合场景:与工厂模式很类似,只不过用构造函数伪装了下,这里要注意的是使用new关键字如果构造函数没明确return默认是返回新创建的对象,如果明确了 return o 会返回手动创建的对象,如果返回的是基础类型默认还是返回新创建的对象
这个模式可以在特殊的情况下用来为对象创建构造函数。假设我们想创建一个具有额外方法的特殊数组。由于不能直接修改 Array 构造函数,因此可以使用这个模式。
function SpecialArray(){ //创建数组 var values = new Array(); //添加值 values.push.apply(values, arguments) //添加方法 values.toPipedString = function(){ return this.join("|"); }; //返回数组 return values; } var colors = new SpecialArray("red", "blue", "green");alert(colors.toPipedString()); //"red|blue|green"
缺陷:返回的对象与构造函数或者与构造函数的原型属性之间没有关系;不能依赖 instanceof 操作符来确定对象类型
稳妥构造函数模式
function Person(name, age, job) {
var o = new Object()
o.sayName = function() {
alert(name)
}
return o
}
var friend = Person("Nicholas", 29, "Software Engineer")
friend.sayName() //"Nicholas"
friend.name = "daisy" // 没用
适合场景:稳妥模式与寄生模式不同在于没用this和new关键字,不会创建新对象。没用公共属性,稳妥对象最适合在一些安全的环境中。
缺陷:稳妥构造函数模式也跟工厂模式一样,无法识别对象所属类型。
https://juejin.cn/post/6903403553046396935