对象基础创建模式
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;
}
}
从而保证创建该对象的实例时,属性的方法不会被重复创建