故事缘由
一天,一哥们说,骚年,我发现撸码一段时间后,回看以前自己写的代码,水到掉渣了,我们来重构吧!我想,既然要重构,逼格肯定要比之前的高才行啦,等等?,让我回顾下JS对象的创建,一眼看穿?JS对象的创建
对象的创建各大博文都介绍的非常详细了,在这里就不班门弄斧了,只是想总结下各种创建对象的方法以及其优缺点。?
创建对象有4️⃣大法宝
1、通过Object构造函数创建(只能创建单个对象)
let obj = new Object();
obj.name = '命名最头痛'
obj.age = 18
obj.job = function() {
console.log('programer')
}
这种方法是创建单一对象法,没封装性可言,且每添加一个属性都要写一次obj,代码可读性也不是很好,了解就好。
2、通过字面量方式创建对象(也只能创建单个对象)
let obj = {
name: '命名最头痛',
age: '18,
job: function() {
console.log('programer')
}
};
这种方法也是单一对象法,对比上一个方法,虽然增强了可读性,但是依旧没解决封装性问题,我们期望可以将共同部分封装起来,增强复用性,通过传参的方式去创建,这时,通过函数法应运而生。?
3、工厂模式?
工厂工厂,就像一个工厂一样把东西包起来
function createObj (name, age, job) {
let obj = new Object();
obj.name = name,
obj.age = age,
obj.job = function() {
console.log(job)
}
return obj;
}
let obj = createObj('命名最头痛', 18, 'programer')
工厂模式的设计思路就是在函数中创建一个对象,最后返回这个对象,每次调用时,都能创建一个新对象
这种方法虽然解决了封装性问题, 但是并不知道对象的类型,依旧无法满足我们需求,此时新的模式又出现了。?
4、构造函数模式
我们知道,在ECMA中的构造函数可用来创建特定类型的对象,除了通过Object构造函数,我们还可以创建自定义构造函数,定义对象类型的属性。
function Obj (name, age, job) {
this.name = name
this.age = age
this.job = function() {
console.log(job)
}
}
let obj1 = new Obj('命名最头痛', 18 'programer')
let obj2 = new Obj('命名最头痛', 18 'programer')
之前一直在纠结构造函数和函数有什么区别,后来发现,任何函数,只要通过new操作符来调用,那它就可以作为构造函数,而任何函数,如果不通过new操作符来调用,那它跟普通函数也不会有什么两样,同样的性质,只不过用在不同的地方,叫法不同罢了。
在这里,我们发现了一个神秘新单词,new,没错啦,new这个词就是用于创建对象的,那么new的背后到底做了什么呢?
①创建一个新对象
②将构造函数的作用域赋值给新对象(因此this指向了这个新对象)
③执行构造函数中的代码(为这个新对象添加属性)
④返回新对象
好啦,我们知道new可以创建一个对象,那么创建完的东西叫他什么呢?我们称之为实例。
创建一个实例后,实例会附带一个constructor(构造函数)属性,通过这个属性可以找到它的构造函数,如果你不理解这句话,我打个比喻就好理解了,创建对象就好比蝌蚪妈妈,实例就好比小蝌蚪,蝌蚪妈妈产下小蝌蚪后会在他们身上留下胎记(constructor),小蝌蚪通过这个胎记去找回他母亲。
那么这种方法对比上一种方法有什么优点呢?
创建自定义的构造函数意味着可以将它的实例标识为一种特定的类型,这解决了工厂模式无法识别对象类型问题。
完美,对象识别问题解决了,这意味着当看见一个对象时,我们有办法(通过constructor)找到它的“母板”了。
构造函数看似很完美,但是还是会有不足。我们都知道,每创建一个构造函数就是实例化一个对象,同个构造函数创建出来的对象,他们的同名函数是不相等的,说白了点,以这种方式创建函数,会导致不同的作用域链和标识符解析。如果还是不明白,?没有什么是一副图搞不掂的
这个图意思是:通过Person构造函数创建的两个对象p1和p2,他们的同名函数(共同方法)是不相等的。
尾声
如果我们期望这个方法是一样的,有没有办法解决呢?答案是肯定的,请听下文分解。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。