// 1.工厂方式创建对象:面向对象中的封装函数(内置对象)
简单来说就是封装后的代码,简单的工厂模式是很好理解的,关于它的作用,就是利用面向对象的方法,把一些对象封装,使一些占用空间多的,重复的代码封装起来。实现方法非常简单,也就是在函数内创建一个对象,给对象赋予属性以及方法再将对象返回即可。
function createPerson(name){
var obj=new Object();//1.原料
//2.加工
obj.name=name;
obj.showName=function(){
alert(this.name);
}
return obj;//3.出厂
}
可以看出,使用工厂模式,可以重复调用这个per函数来生成不同属性值得对象,这就像工厂一样,批量生产,里面的原料,加工,出厂都很清晰。但是你会发现工厂模式是无法识别对象的类型,因为全都是object,不像Date,Array等,但是构造函数就不是了。这还只是简单的工厂模式,复杂的工厂模式(抽象模式)等以后再回来详细了解。
//2、构造函数创建对象
//当new去调用一个函数,这个时候函数中的this就是创建出来的对象,而且函数的返回值就是this(隐式返回)
//new后面的函数叫做构造函数
// <1>有参数的构造函数
function CreatePerson(name){
this.name=name;
this.showName=function(){
alert(this.name);
}
}
var p1=new CreatePerson('小米');
p1.showName();
// <2>无参数的构造函数
function CreatePerson(){}
var p1=new CreatePerson();
p1.name="吃丸子";
p1.showName=function(){
alert(p1.name);
}
p1.showName();
// 3.用原型方式
function Person(){}js规定每一个创建的函数都有prototype(原型)属性,这个属性是指针,指向一个对象,而这个对象的用途是包含由特定类型的所有实例所共享的属性和方法,使用原型对象就可以让所有实例对象均包含这些属性及方法。
Person.prototype.name="hello";
Person.prototype.showName=function(){
alert(this.name);
}
var p1=new Person();
p1.showName();
关于原型模式的缺点,我想也是很明显的,它省略了构造函数传递初始化参数这一环节,结果所有实例均在默认情况下取得了相同的属性值,虽然你可以在后来做出更改,但一点都不方便,这样还不是最大的问题,原型模式最大的问题是在于共享的本性所导致的,由于共享,因此一个实例修改了引用,另一个也随之更改了属性。因此一般不会单独使用原型模式。
//4.混合构造函数和原型模式
function CreatePerson(name){
this.name=name;
}
CreatePerson.prototype.showName=function(){
alert(this.name);
}
var p1=new CreatePerson("加油");
p1.showName();
var p2=new CreatePerson("加油呀!");
p2.showName();
alert(p1.showName==p2.showName);//true;原因:都是在原型下面,在内存中只存在一份,地址相同
function per(name){
this.name=name;
}
per.prototype.say=function(){
alert(this.name);
}
var per1=new per('lyf');
var per2=new per ('xiaoai');
per1.say();
per2.say();
//<5>动态模式
function per(name){
this.name=name;
if(typeof this.say!='function'){
// 这段代码只执行了一次
per.prototype.say=function(){
console.log(this.name);
}
}
}
var per1=new per('katherine');
var per2=new per('xiaoai');
per1.say();
per2.say();
动态原型模式将所有的信息都封装进了构造函数中,通过构造函数中初始化原型,仅第一个对象实例实例化时初始化,通过判断该方法是否有效存在而选择是否需要初始化。大白话就是:如果去掉if的话,每new一次(即每当一个实例对象生产时),都会重新定义一个新的函数,然后挂到per.prototype.say上,而实际上,只需要定义一次就够了,因为所有的实例都会共享此属性的,所以如果去掉if的话,会造成没有必要的时间和空间的浪费,而加上if后,只在new第一次实例化时会定义say方法,之后都不会再定义了。可以看出对于这种模式创建的对象,是最好的了。