js对象模式的理解
一.工厂模式:
a)现实中的工厂差不多
b)在函数内部创建了一个新的空对象,最后返回这个对象(对象不会暴露)
c)缺点:虽然new的是共同的一个函数,但是其中的方法做对比,返回false,也就意思说,new的函数,中的方法,不是共享(不是同一个地址).
eg:
//现实中的工厂===>生产一瓶西瓜汁
//1》西瓜 ====>new Object();
//2》榨汁 ====>对象的属性
//3》装瓶,贴商标.... ====>对象的方法
//4》大货车拉出厂子卖
function createObject(){
var obj = new Object();
obj.name = "西瓜汁"; //属性
obj.run = function(){//方法
return "贴了商标了";
};
return obj;//出厂==》卖
}
var o1 = new createObject();
var o2 = new createObject();
console.log(o1.name);//西瓜汁
console.log(o2.name);//西瓜汁
console.log(o1.run == o2.run);//false
二.构造函数模式
a)和工厂模式区别:
构造函数中,不需要在内部创建对象(给这个对象添加属性,方法,也不用return 对象)
b)如果要写构造函数模式,函数的首字母需要大写
new Array()
new String()
new Date()
new RegExp();
c)缺点:虽然new的是共同的一个函数,但是其中的方法做对比,返回false,也就意思说,new的函数,中的方法,不是共享(不是同一个地址)(跟工厂模式是相同的缺点)
function CreateFn(){ //首字母要大写
this.str = "构造函数";
this.run = function(){
return "js构造函数方法";
}
}
//1>其实构造函数就是普通函数,只不过首字母需要大写了,为了让别人知道,这个函数是一个构造函数
//2>函数内部写变量不在是var str ===> this.str;
var obj1= new CreateFn();
var obj2= new CreateFn();
/*console.log(obj1.str);
console.log(obj2.str);*/
console.log(obj1.run == obj2.run);//false
三.原型模式
1>每当创建一个函数,都有一个prototype(原型)的属性
2>原型(prototype)这个属性的指针,指向于一个对象,而这个对象的用途可以由特定类型的所有实例“共享”的方法和属性.
3>原型(prototype)是共享所有的属性和方法,也就是,如果new了2个函数(实例化),他们的方法是共享的,做对比,返回true,共同使用一个地址
a)缺点 :因为是共享的方法,公用一个地址,如果后期一个修改,所有对象的方法就都修改了
function fn(){
fn.prototype.userName = "张三";
fn.prototype.arr = [1,2,3];
//把fn的原型的属性(userName)共享给对象了
fn.prototype.run = function(){
return "这是一个共享的方法";
}
}
var obj1 = new fn();
var obj2 = new fn();
console.log(obj1.userName);//张三
console.log(obj2.userName);//张三
console.log(obj1.run == obj2.run);//true
obj1.userName = "李四";
(此处username为值类型,储存在栈中,与地址无关,所以只改变自身)
console.log(obj1.userName);//李四
console.log(obj2.userName);//张三
obj1.arr[1] = "你好数组";
console.log(obj1.arr);//你好数组
console.log(obj2.arr);//你好数组
-----------------------------------------------------------------------------------------------------
自己话总结
工厂模式和构造函数模式:
①.obj1 new和obj2 new都形成了两个不同的储存块,储存包含栈和堆,obj1和obj2的基本类型储存在各自的栈中,修改其中一个不影响另一个,比较判断的时候,只要值相同就返回true
②.obj1和obj2的复杂类型(比如数组)或者方法的地址都储存在各自的栈中,具体内容储存在各自的堆中,由于地址不同,修改其中一个不影响另一个,比较判断无论内容是否相同都返回false
原型模式:
①.obj1和obj2 基本类型跟工厂模式和构造模式相同
②.obj1和obj2 的方法或者复杂类型用原型prototype定义之后,就共用相同的地址,所以修改其中一个会影响另一个,判断比较的时候 永远是true
-----------------------------------------------------------------------------------------------------
四.组合使用构造器+原型模式
a>构造函数:定义实例属性
b>原型:定义和共享属性
优点:每一个实例都会有自己的一份实例属性,但又同时共享着方法
function CreateFn(name,age){
this.userName = name;
this.age = age;
this.arr = [1,2,3];
};
CreateFn.prototype.run = function(){
return "我是共享的";
};
var obj1 = new CreateFn("张三",18);
var obj2 = new CreateFn("李四",20);
console.log(obj1.userName);//张三
console.log(obj2.userName);//李四
console.log(obj1.run == obj2.run);//true
console.log(obj1.arr == obj2.arr);//false
五.动态原型模式
是将所有的信息(属性和方法)都封装在构造函数中,而通过构造函数来初始化原型
解决:第一个对象实例化的时候就初始化原型,后面的就不需要初始化
function CreateFn(){
this.userName = "张三";
if( typeof this.run !="function" ){
console.log(1);//只输出一次1 说明这段代码只运行一次,
//共享的代码运行一次即可
CreateFn.prototype.run = function(){
return "共享的run方法";
}
}
}
var obj1 = new CreateFn();
var obj2 = new CreateFn();