为什么要使用工厂模式和构造函数方式创建对象?
虽然Object构造函数(var obj = new Object();)或者字面量(var person={})可以创建单个对象,但是,他有一个明显的缺点,那就是:重复造轮子,产生大量的重复性代码,为了解决这个问题,我们就开始使用工厂模式和构造函数模式。
什么是工厂模式 它有什么优缺点?
顾名思义,工厂模式就是像工厂一样来创建对象。但这样的解释似乎有点欠妥,高大上一点,工厂模式其实是软件领域中一种广为人知的一种设计模式,这种模式抽象了创建具体对象的过程。开发人员发明了一种函数,用函数来大量创建对象的方法;
下面是工厂模式创建对象的方法:
<pre>
<script>
function creatPerson(name,age,sex){
// var person = {};
// person.name = name;
// person.age = age;
// person.sex = sex;
// return person;
return{
name:name,
age:age,
sex:sex
}
}
var person1 = creatPerson("李四",18,"男")
var person2 = creatPerson("李四z",28,"男")
var person3 = creatPerson("李四zzz",30,"男")
console.log(person1);
console.log(person2);
console.log(person3);
</script>
</pre>
虽然工厂模式可以创建多个相似的对象,但是却没有解决对象的识别问题(不知道这个对象的类型)。
什么是构造函数模式,它和工厂模式比较有哪些好处?它自身又有那些缺点?
1.实例如下:
<pre>
<script>
function Person(name,age){
this.name = name;
this.age = age;
}
var p = new Person("张三","10s岁");
var p2 = new Person("李四","16岁");
console.log(p);
console.log(p2);
// console.log(p instanceof Object);
</script>
</pre>
这个例子中,Person()函数取代了person()函数;睁大你的眼睛,构造函数创建对象的函数名Person()明显是开头大写,这是构造函数的惯例,为了区分和普通函数的区别,因为构造函数也是函数,只不过可以创建对象而已。
要创建Person()的新实例,必须使用new,即和使用var person1 = new Person()差不多,实际上会经历一些步骤:
- 创建一个新的对象;
- 将构造函数作用域赋给新的对象(即this指向新对象);
- 执行构造函数里面的代码;
- 返回新的对象。
构造函数和普通函数的区别在哪?
1.构造函数和普通函数唯一的区别是他们的调用方式不同。
2.任何函数只要通过new来调用,那它就可以作为构造函数,而任何函数,如果不通过new操作符来调用,他就是普通的函数。
实例如下:
<pre>
//当做构造函数来使用
var person1 = new CreatePerson('张三',18,'男');
person1.sex(); //'男'
//构造函数当做普通函数使用
CreatePerson('张三',18,'男')
window.sex();//'男'
</pre>
构造函数有哪些不足之处?
我们可以参照上面的构造函数的第一个实例,可以得出这种方式创建函数实例创建的对象都包含一个不同的Function实例,所以,不同实例上的同名函数是不相等的,证明如下:
<pre>console.log(person1.sex == person2.sex);//false</pre>
2.因此以上的写法可以这样简化:
<pre>function CreatePerson(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
function sexes(){
console.log(this.sex);
}
var person1 = new CreatePerson('张三',18,'男');
var person2 = new CreatePerson('李四',18,'男')</pre>
这个时候的person1.sex和person2.sex就是相等的.
我们把函数放在构造函数的外面作为全局函数,因此person1和person2对象就共享了在全局作用域中定义的同一个sexes函数。但是问题又来了:在全局作用域中定义的函数实际上只能被某个对象调用,这让该全局作用域有点名不副实。更让然无法接受的是:如果对象需要定义很多方法,那么就要定义很多个全局函数,那么我们这个自定义的引用类型就丝毫没有封装性可言了。因此我们需要另一种高大上的模式,——原型模式(prototype)