起初接触JS时常见的简单地建立单个对象的方式有下面三种:设计模式
以上三种方式在须要建立不少对象时会产生大量重复代码。显然须要更高效的方式,下面将介绍7种建立对象的方式安全
工厂模式正是源自设计模式中的工厂模式,其基本思想:函数
function createPerson(name, age) {
var obj = new Object()
obj.name = name
obj.age = age
obj.getName = function() {
console.log(this.name)
}
return obj
}
var person1 = createPerson("AAA", 23)
person1.getName() //AAA
var person2 = createPerson("BBB", 30)
person2.getName() //BBB
复制代码
构造函数可建立特定类型的对象,相似Object和Array(实际上Object和Array自己就是构造函数)post
function Person(name, age) {
this.name = name
this.age = age
this.getName = function() {
console.log(this.name)
}
}
var person1 = new Person("AAA", 23)
person1.getName() //AAA
var person2 = new Person("BBB", 30)
person2.getName() //BBB
复制代码
经过上面代码咱们能够看到构造函数模式:优化
构造函数其实也是个函数,只是能够经过new调用来建立对象,固然也可做为普通函数使用ui
//做为普通函数使用
Person("CCC", 24)
Person.getName() //CCC
//在一个对象内调用
var obj = {}
Person.call(obj, "DDD", 25)
obj.getName() //DDD
复制代码
console.log(person1 instanceof Object) //true
console.log(person1 instanceof Person) //true
复制代码
console.log(person1.getName === person2.getName) //false
复制代码
原型模式即经过原型对象来实现属性和方法的共享,实例对象不会建立各自的副本this
要理解原型模式,建议先理解透彻JS原型的概念——推荐阅读一张图完全KO原型链(prototype,__proto__)spa
function Person() {
}
Person.prototype.name = "AAA"
Person.prototype.age = 23
Person.prototype.getName = function() {
console.log(this.name)
}
var person1 = new Person()
person1.getName() //AAA
var person2 = new Person()
person2.name = "BBB"
person2.getName() //BBB
console.log(person1.getName === person2.getName) //true
复制代码
然而原型对象也存在缺陷——对于引用类型的属性,各实例对象间指向同一个地址,某个对象修改了属性,全部对象都会受到影响prototype
function Person() {
}
Person.prototype.arr = [1,2,3]
Person.prototype.getArr = function() {
console.log(this.arr)
}
var person1 = new Person()
person1.arr.push(4)
person1.getArr() //1,2,3,4
var person2 = new Person()
person2.getArr() //1,2,3,4
person1.arr.push(5)
person1.getArr() //1,2,3,4,5
person2.getArr() //1,2,3,4,5
复制代码
组合模式即组合构造函数模式和原型模式,取两者之长,构造函数模式用于定义实例的属性,原型模式用于定义方法和共享的属性设计
function Person(name, age) {
this.name = name
this.age = age
this.arr = [1,2,3]
}
Person.prototype = {
getName: function() {
console.log(this.name)
}
}
var person1 = new Person("AAA", 23)
person1.arr.push(4)
console.log(person1.arr) //1,2,3,4
person1.getName() //AAA
var person2 = new Person("BBB", 30)
console.log(person2.arr) //1,2,3
person2.getName() //BBB
复制代码
刚说组合模式是承认度最高的一种模式,然而也有些美中不足——每建立一个实例对象,原型方法都被重复定义一次
动态原型模式正是解决这个问题,使用if语句,使得原型方法只初始化一次
function Person(name, age) {
this.name = name
this.age = age
//这里只须要使用任何一个方式或属性,不必定是getName,getAge也能够
//只要保证if里面的代码只执行一次就行
if(typeof this.getName !== 'function') {
Person.prototype.getName = function() {
console.log(this.name)
}
Person.prototype.getAge = function() {
console.log(this.age)
}
}
}
var person = new Person("AAA", 23)
person.getName() //AAA
复制代码
长得和工厂模式同样,但调用方式和构造函数模式同样的模式,经过new调用构造函数,本该返回一个实例对象,但return语句重写了构造函数的返回值
function Person(name, age) {
var obj = new Object()
obj.name = name
obj.age = age
obj.getName = function() {
console.log(this.name)
}
return obj
}
var person = new Person("AAA", 23)
person.getName() //AAA
复制代码
这种方式和工厂模式没什么不一样,要说不一样的就是经过new来调用,仍然存在工厂模式的没法判别对象类型的问题
我的认为这是一种多余的方式,复杂而很差理解,也没有什么应用场景
先介绍一个概念——稳妥对象:
稳妥构造函数模式和工厂模式相似,但遵循稳妥对象的原则
function Person(name, age) {
var obj = new Object()
//getName是惟一读取name的方式
obj.getName = function() {
console.log(name)
}
return obj
}
var person = Person("AAA", 23)
person.name = "BBB" //无效
person.getName() //AAA
复制代码
工厂模式:解决了大量重复代码的问题,但没法判别对象类型
构造函数模式:实例对象又具体的类型,但每一个实例对象都有方法的副本,形成内存浪费
原型模式:可共享方法和属性,但存在引用类型相互影响的问题
组合模式:取构造函数模式和原型模式之长 (最经常使用)
动态原型模式:优化了组合模式
寄生构造函数模式:相似工厂模式,只是经过new调用
稳妥构造函数模式:相似工厂模式,只是提高了安全性
但愿本文对你有帮助,更多文章将持续更新……
感谢你的点赞和鼓励
与本文相关的文章有: