一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
”谈一谈“之ES5创建对象的7种方式
在javascript这门语言中,对象是一个说简单就简单,说难就难的一个点。 今天就聊一聊创建的几种方式。
1.工厂模式
function Factory (a,b,c){
let obj = {}
obj.a = a;
obj.b = b;
obj.c = c;
obj.callA = function(){
alert(this.a+ ':a')
}
return obj
}
let fa = Factory('a','b','c');
console.log(fa)
打印结果:
缺点:这里确实创造出了一个对象,但是不清楚他的原型是谁,可以看到construct指向了Object。
联想:简单的理解就是有一个工厂,工厂生产汽车,汽车是生产出来了,但是我不清楚生产汽车发动机的厂商是哪个,这样客户肯定不会买单的,所以这样的方式创建是不推崇的。
2.构造函数
function Constru (a,b,c){
this.a = a;
this.b = b;
this.c = c;
this.callA = function(){
alert('a')
}
}
let con = new Constru('a','b','c');
console.log(con)
打印结果:
这边结果和工厂模式类似,可以看出这个对象创建出来的构造函数指向了Constr。在new出的过程中发生了以下的4个步骤:
- 创建一个新对象
- 将构造函数的作用域给了新对象(改变this的指向)
- 执行构造函数中的代码
- 返回一个新的对象
相比工厂模式,这边明显的能清楚的知道属于那个类型,可以使用instanceof来验证
fa in stantceof Object //true
fa in stantceof Factory //true
这就是构造函数方式优于工厂模式的一个地方。
缺点:构造函数的方式设计还是存在了一定的问题,比如我创建了两个对象
let co1 = new Constru('a','b','c');
let co2 = new Constru('a','b','c');
这两个对象的callA这个方法其实是一样的,我们重复的去在这个对象上面创建了这两个方法,这样设计明显是多余的,也不符合变成的封装性和继承性。因此有了原型模式。
联想:我有个工厂,打开机器后,这个工厂就会以机械的方式返回你需要的产品,这样看起来很快捷。但是比如我需要生产一个柜子,柜子里面会用到螺丝,这个螺丝每次我都要去造一次,这样效率会大大的减少。
3.原型模式
function Proto(){}
Proto.prototype.a = 'a'
Proto.prototype.b = 'b'
Proto.prototype.c = 'c'
Proto.prototype.callName = function(){
alert('a')
}
let po = new Proto()
打印结果:
可以看出,这样返回的对象是一个空的,但是原型中出现了callName和一些属性,而且每实例化出一个属性或者方法他们都指向了同一个方法或属性。这个其实就是实现了一个简单的继承,具体的继承后面会提到。这边知识点挺多,具体及不多提了,后续可能会陆续补充。
缺点:原型中所有属性是被很多实例共享的,这种共享对于函数非常合适。对于那些包含基本值的属性倒 也说得过去,毕竟(如前面的例子所示),通过在实例上添加一个同名属性,可以隐藏原型中的对应属 性。然而,对于包含引用类型值的属性来说,问题就比较突出了。
联想:以上面的例子继续说,现在我发现效率有点低,那我就把所有的零件都分配给不通的部门去做,这个部门是做螺丝的,那个部门是处理板子的,这个部门是拼装的。这样问题确实解决了,效率也挺快,但是出现个问题。我做产品A的时候用的螺丝是长的,做好后,又来了产品B,现在产品B螺丝用的是短的,这不完了吗.....,那如何解决上面两个问题呢?精髓就是:I have pen,I have apple ,emm~, applePen
组合使用构造函数模式和原型模式
function Contac(a){
this.a = a
}
Contac.prototype.callName = function(){
alert('a')
}
let po = new Contac()
person1.constructor == Person
这个就是我们开发中常用到的一些方法。在需要独立创建的时候,可以在构造函数中创建,遇到一些公用的没有必要重复申请的就放挂在原型上。分工有序,互不干扰。
寄生构造函数模式。
function Factory (a,b,c){
let obj = {}
obj.a = a;
obj.b = b;
obj.c = c;
obj.callA = function(){
alert(this.a+':a')
}
return obj
}
let fa = new Factory('a','b','c');
console.log(fa)
寄生构造函数类似工厂模式,就是多了一个new,没有什么特别之处。
极度不推荐,只是知道能够创建一个对象,创建出来的对象也不能知道原型指向哪里的,所以能不用就不用。
稳妥构造函数模式
function Factory (a,b,c){
let obj = {}
obj.a = a;
obj.b = b;
obj.c = c;
obj.callA = function(){
alert('a')
}
return obj
}
let fa = new Factory('a','b','c');
console.log(fa)
在这个模式中,指的是没有公共属性和函数,函数不能使用new 和this,在符合此情况下,可以使用,和上面的寄生构造函数类似,只要知道符合以上说的条件下,迫不得已可以使用。