JS五种设计模式

对象基础创建模式

    var hero=new Object();
    hero.name="无双剑姬";
    hero.passive="无双剑舞";
    hero.skill=function(){
        return this.name+"的被动技能是"+this.passive;
    }
    document.write(hero.name+"<br/>");
    document.write(hero["passive"]+"<br/>");
    document.write(hero.skill+"<br/>");
    document.write(hero.skill()+"<br/>");

输出结果

无双剑姬
无双剑舞
function (){ return this.name+"的被动技能是"+this.passive; }
无双剑姬的被动技能是无双剑舞

说明
原理:声明对象,后续给对象加属性和方法

优点:可以直观的看出对象有属性,方法

缺点:如果有多个类型,需要创建多个实例;

虽然用Object构造函数或对象字面量都可以创建对象,但是有很大的缺点,就是我们在使用同一个接口创建很多对象的时候,会产生大量的重复代码。


一、工厂模式

    //工厂模式
    function creatHero(name,passive) {
        var hero=new Object();
        hero.name=name;
        hero.passive=passive;
        hero.skill=function(){
            return this.name+"的被动技能是:"+this.passive;
        }
        return hero;
    }
    var jianji=creatHero("无双剑姬","无双剑舞");
    var daomei=creatHero("艾瑞莉娅","艾欧尼亚热诚");
    document.write(jianji.name+"<br/>");
    document.write(daomei["passive"]+"<br/>");
    document.write(jianji.skill()+"<br/>");
    document.write(daomei.skill()+"<br/>");
    document.write(jianji==daomei);//两个对象实例的地址是不同的,代表两个对象占用两个地址

输出结果

无双剑姬
艾欧尼亚热诚
无双剑姬的被动技能是:无双剑舞
艾瑞莉娅的被动技能是:艾欧尼亚热诚
false

说明

原理:将原始方式封装到函数中,并返回这个对象

优点:同一类型同一属性可以重复调用;

缺点:同一类型不同属性值的不能调用;


二、构造函数模式

    function hero(name,passive){
        this.name=name;
        this.passive=passive;
        this.skill=function(){
            return this.name+"的被动技能是:"+this.passive;
        }
    }
    var jianji=new hero("无双剑姬","无双剑舞");
    var daomei=new hero("艾瑞莉娅","艾欧尼亚热诚");
    document.write(jianji.skill()+"<br/>");
    document.write(daomei.skill()+"<br/>");
    document.write(jianji==daomei);
    document.write("<br/>");
    document.write(jianji instanceof people);
    document.write("<br/>");
    var ruiwem=new Object();
    hero.call(ruiwem,"放逐之刃","符文之刃")//对象冒充
    document.write(ruiwem.skill()+"<br/>");
    var kasha=new Object();
    hero.apply(kasha,["虚空之女","体表活肤"]);//对象冒充
    document.write(kasha.skill()+"<br/>");

输出结果

无双剑姬的被动技能是:无双剑舞
艾瑞莉娅的被动技能是:艾欧尼亚热诚
false
true
放逐之刃的被动技能是:符文之刃
虚空之女的被动技能是:体表活肤

说明:

原理:在构造函数内使用 this 关键字,创建属性和方法。再使用 new 运算符创建实例,通过传参生成不同的实例。

优点:该方式解决了以上模式所遇到的问题

缺点:构造函数会重复生成函数,为每个对象都创建独立的函数版本

注意
 //知识点1: 那么工厂模式和构造函数模式有什么区别呢:
  /*
  * 没有显式地创建对象
  * 直接把属性和方法赋值给了this
  * 没有return语句
  * 构造函数的前面有一个new;
  * */

  // 知识点2:

  /*
  * 通过new的构造函数会经过四个阶段:
  * 1:创建一个新对象;
  * 2:把this赋值给这个新对象
  * 3:执行构造函数中的代码
  * 4:返回新对象
  * */


三、原型模式

(1)第一种写法

function hero(){
        hero.prototype.name="无双剑姬";
        hero.prototype.passive="无双剑舞";
        hero.prototype.skill=function(){
            return this.name+"的被动技能是:"+this.passive;
        }
    }
    var jianji=new hero();
    jianji.Hp=[];
    var daomei=new hero();
    document.write(jianji.skill()+"<br/>");
    document.write(daomei.skill()+"<br/>");
    document.write(daomei.skill==daomei.skill);//说明他们引用的地址是同一个
    //这时所有实例化的方法,其实引用的是同一个地址,指向prototype对象,因此提高了运行效率
    document.write("<br/>");
    jianji.name="菲奥娜";
    document.write(jianji.skill()+"<br/>");
    document.write(daomei.skill()+"<br/>");
    document.write(jianji.constructor);

输出结果

无双剑姬的被动技能是:无双剑舞
无双剑姬的被动技能是:无双剑舞
true
菲奥娜的被动技能是:无双剑舞
无双剑姬的被动技能是:无双剑舞
function hero(){ hero.prototype.name="无双剑姬"; hero.prototype.passive="无双剑舞"; hero.prototype.skill=function(){ return this.name+"的被动技能是:"+this.passive; } }

(2)第二种写法

function hero() {}
    hero.prototype={
        name:"无双剑姬",
        passive:"无双剑舞",
        skill:["空破斩","劳伦特心眼刀"],
        run:function() {
            return this.name+"的被动技能是:"+this.passive;
        }
    }
    var jianjiA=new hero();
    var jianjiB=new hero();
    document.write(jianjiA.skill+"<br/>");
    document.write(jianjiB.skill+"<br/>");
    jianjiA.skill.push("剑术");
    jianjiB.skill.push("无双挑战");
    document.write(jianjiA.skill+"<br/>");
    document.write(jianjiB.skill+"<br/>");
    document.write(jianjiA.constructor);//弹出包含了系统底层代码的构造函数,但是不影响使用

输出结果

    空破斩,劳伦特心眼刀
    空破斩,劳伦特心眼刀
    空破斩,劳伦特心眼刀,剑术,无双挑战
    空破斩,劳伦特心眼刀,剑术,无双挑战
    function Object() { [native code] }

说明
原理:创建一个构造函数,再函数外为通过prototype方式添加属性和方法,最后通过new 运算符生成实例

优点:语义上,看起来所有属性都是同一个对象,解决了上两种方式所遇到的问题;

缺点:不能通过给构造函数传递参数来初始化属性的值,而且如果其中某个实例属性重新赋值,会导致其他的实例同一属性也会发生变化


四、构造函数+原型函数的组合模式

function hero(name,passive){
    this.name=name;
    this.passive=passive;
}
 hero.prototype={
    skill:function(){
        return this.name+"的被动技能是:"+this.passive;
    }
 }
 var jianji=new hero("无双剑姬","无双剑舞"+"<br/>");
 var daomei=new hero("艾瑞莉娅","艾欧尼亚热诚"+"<br/>");
 var ruiwen=new hero("放逐之刃","符文之刃"+"<br/>");
 document.write(jianji.skill());
 document.write(daomei.skill());
 document.write(ruiwen.skill());

输出结果

无双剑姬的被动技能是:无双剑舞
艾瑞莉娅的被动技能是:艾欧尼亚热诚
放逐之刃的被动技能是:符文之刃

说明
混合搭配使用构造函数和原型方式。将所有的属性,不是方法的定义在函数中(构造函数的方式),将所有属性值为方法的利用prototype在函数之外定义(原型方式)。

原理:利用构造函数方式创建函数的不同的部分,利用原型方式来定义相同的方法和属性

优点:此种 方式即符合语义又可以扩展新的属性和方法

推荐使用这样的方式创建对象,这样有好处。


五、构造函数+原型的动态原型模式

错误写法

function hero(name,passive){
    this.name=name;
    this.passive=passive;   
    hero.prototype.skill=function(){
        return this.name+"的被动技能是:"+this.passive;
    }
    document.write("初始化结束"+"<br/>");
}
var jianji=new hero("无双剑姬","无双剑舞"+"<br/>");
 var daomei=new hero("艾瑞莉娅","艾欧尼亚热诚"+"<br/>");
 var ruiwen=new hero("放逐之刃","符文之刃"+"<br/>");
 document.write(jianji.skill());
 document.write(daomei.skill());
 document.write(ruiwen.skill());

输出结果

初始化结束
初始化结束
初始化结束//方法初始化了三次
无双剑姬的被动技能是:无双剑舞
艾瑞莉娅的被动技能是:艾欧尼亚热诚
放逐之刃的被动技能是:符文之刃

正确写法

function hero(name,passive){
    this.name=name;
    this.passive=passive;
    if(typeof this.skill!="function"){
        hero.prototype.skill=function(){
            return this.name+"的被动技能是:"+this.passive;
        }
        document.write("初始化结束"+"<br/>");
    }
}
var jianji=new hero("无双剑姬","无双剑舞"+"<br/>");
 var daomei=new hero("艾瑞莉娅","艾欧尼亚热诚"+"<br/>");
 var ruiwen=new hero("放逐之刃","符文之刃"+"<br/>");
 document.write(jianji.skill());
 document.write(daomei.skill());
 document.write(ruiwen.skill());

输出结果

初始化结束
无双剑姬的被动技能是:无双剑舞
艾瑞莉娅的被动技能是:艾欧尼亚热诚
放逐之刃的被动技能是:符文之刃

说明
.动态原型方式可以理解为混合构造函数,原型方式的一个特例

.该模式中,属性为方法的属性直接在函数中进行了定义,但是因为

if(typeof this.skill!=”function”){
hero.prototype.skill=function(){
return this.name+”的被动技能是:”+this.passive;
}
}
从而保证创建该对象的实例时,属性的方法不会被重复创建

详细面对对象解释

https://www.cnblogs.com/chenmeng0818/p/6508755.html

猜你喜欢

转载自blog.csdn.net/weixin_42952665/article/details/82011516
今日推荐