1.独立声明模式
var fn1 = new Object(); fn1.name = '张三'; var fn2 = new Object(); fn2.name = '李四';
优点:创建的每个对象之间互相独立,不会混淆
缺点:结构相同的对象不能重用
2.工厂模式
function factory(name,age,obj){ var o = new Object(); o.name = name; o.age = age; o.obj = function(){....}; return o; }
优点:每次创建类似结构的对象直接调用factory()方法传参即可;
缺点:每次创建出来的对象都是属于Object()对象,本质是一样的,要区分的话就不好区分了
3.构造函数模式
function Obj(name,age){ this.name = name; this.age = age; }; var fn1 = new Obj('张三',22); var fn2 = new Obj('李四',16);
优点:解决了对象复用和传参初始化的问题;
缺点:创建的对象之间不能共享属性
4.原型模式
function Obj(){}; obj.prototype.name = '张三'; obj.prototype.age = 26; obj.prototype.arr = [1,2,3]; var fn1 = new Obj(); fn1.name = '李四'; fn1.arr.push(4); var fn2 = new Obj(); fn2.age = 22; fn2.arr;//[1,2,3,4]
优点:所new出来的对象在prototype中的属性是共享的,能保证所new的对象实例的属性完全统一,修改实例的属性值不会影响prototype中的值
缺点:当含有引用类型的属性时,引用类型的值是存放在prototype中的,直接在对象中修改引用类型就把所有的引用类型都给修改了; 忽略了初始化传参,所有new出来的对象的属性都是一致的,需要手动再赋值
5,原型字面量模式(和原型模式本质上是一样的)
function Obj(){}; Obj.prototype = { constructor : Obj, name : '张三', age : 22 };
继承了原型模式的所有优缺点,单也有自己的优缺点
优点:更好的体现了封装的特性,便于读写
缺点:需要手动的去把constructor指向自己
6.构造函数加原型模式
function Obj(fn1,fn2){ //不共享的属性写在构造函数里 this.fn1 = function(){....}; this.fn2 = fn2; } Obj.prototype = { //共享的属性写在原型里 constructor : Obj, name: '张三', age : 22 }
优点: 这种模式完美解决了共享属性与不共享属性的问题,而且可以精确控制,是非常不错的模式。
缺点: 但是此种办法,原型与构造函数相分离,让人感觉很怪异,体现不了封装;
7.动态原型模式
function Obj(name,age){ this.name = name; //不共享的属性 this.age = age; if(typeof arr != 'object'){ //共享的属性 Obj.prototype.arr = ['aaa','bbb']; } }
优点:这个模式继承了上一个模式(构造+原型)的所有优点,同时也完美解决了封装性问题
缺点:此种模式书写原型时不可用字面量模式,会切断实例和新原型之间的联系