1、自定义对象
a. 工厂模式
function Person(name,age){
var person = new Object();
person.name = name;
person.age=age;
person.say=function(){
alert(person.name+" "+person.age);
}
return person;
}
var person1 = Person("xcp",23);
var person2 = Person("lxm",24);
person1.say();
person2.say();
//没有解决对象识别的问题(x么知道对象的类型)
b. 构造函数模?/p>
function Person(name,age){
this.name = name;
this.age = age;
this.say = function(){
alert(this.name+" "+this.age);
}
}
var person1 = new Person("xcp",23);
var person2 = new Person("lxm",24);
person1.say();
person2.say();
//直接属性附gthisQƈ且没有显C的创徏和返回对象;必须用new来创建对?br />alert(person1 constructor Person);//true
alert(person1 instanceof Person); //true
->创徏对象l历以下步骤Q?br /> >创徏一个新对象
>构造函数的作用赋予新对?因此this指向了新对?
>执行构造函数里面的代码Q添加属性)
>q回新对?br /> ->构造函数的问题
>使用构造函数的主要问题Q就是每个方法都要在每个实例上重?/strong>创徏一遍。例如我们上面的alert(person1.say==person2.say) //false
创徏两个同样功能的Function()是完全没有必要的Q况且有this对象在,Ҏ不用在执行代码前把函数l定到特定对象上面。因些,大可以像以下面的代码Q通过把函数定义{Ud构造函数外部解册个问题:
function Person(name,age){
this.name = name;
this.age = age;
this.say = sayFunction(this.name,this.age);
}
function sayFunction(name,age){
alert(name+" "+age);
}
//q样sayFunction只会创Zơ了 //卻Ialert(person1.say==person2.say) //true;
但问题也来了Q如果有很多个方法,p创徏很多ҎQ这h论可L,适用性都不是很好
c. 原型模式
>理解Q我们创建的每一个对象,都有一个prototype属性,q个属性是一个对象,那么q个对象的作用是什么呢Q所有prototype属性都会自动获得一个constructor(构造函?Q这个属性民包含一个指向prototype属性在所函数的指针。Person.prototype.constructor指向Person。而通过q个构造函敎ͼ我们q可以承ؓ原型d其他属性和Ҏ。如图:
.Person对象的prototype属性指向Person原理对象
.Person原理对象的构造方法指向Person对象
.Person实例调用属性和Ҏ的顺序:先查找Person对象是否h此属性和ҎQ如果Person对象h则返回,如果没有则先查询Person的原型对像。推出:如果对象本n和原型对象同时具有某个函数和ҎQ以对象本n的属性和Ҏ为准。从q个可以体现出多个对象共享原型所保存?/strong>属性和ҎQ以降低内存开消。但有的时候我们需要用原理对象的属性属性和Ҏ去覆盖原有对象的属性的ҎQ这时我们采?strong>删除原有对象的属性和ҎQdelete Person.name(删除原有对象的name属?.可以使用hasOwnProperty()和isPrototypeof();

>原型与in操作W?br /> .有两U可能用in操作Q单独?"name" in person1)和在for..in里面。单独用in的时候对象能够返回给定属性时q回true(实例和原?
>更加单的原型语法
function Person(){}
Person.prototype={
name:'age',
age:'23',
say:function(){
alert(this.name+" "+this.age);
}
}
//q样写下来就相当?strong>重写了对象的prototype对象Q那原型对象里面的constructor属性就没有?/strong>.但如果我要得到constructor属性怎么办呢Q?br /> Person.prototype={
constructor:Person,//constructor=this,
name:'age',
age:'23',
say:function(){
alert(this.name+" "+this.age);
}
}
>原型中的动态?nbsp;
.׃原型中查找植的过E是一ơ性的Q因此我们对原型对象所做的操作会立d映出来,?br /> function Person(){
}
Person p = new Person();
Person.prototype.say=function(){
alert("hi");
}
p.say(); //hi;q样可以立M现出?br />
//再看看下面的例子
function Person(){}
Person p = new Person();
Person.prototype={
say:function(){
alert("hi");
}
}
p.say(); //error;
//q里Z么就出错了呢Q上一个例子不是好好的?/strong>Q因为第一个例子,只是在prototype原型对象里面d了一个属性,我们在调用say的时候他会查扑֯象本w和原型对象q且是一ơ查询(所以的代码q行完毕Q,所以可以正常的到原型对象里面取出来Q可是后面一个方法呢Q声明对象p他的时候他会找到_proto_指针指向原型对象Q而我用Person.prototype也重构这个原型对象,q当于切断了constructor与是初始原型之间的连接关p,所有p的Q何非本n属性都会出错!
>原生态对象模?/span>
.原型cd不仅体现在自定义对象模型Q包括原生的引用cd都是采用的这U模式,所以我们可以修改引用类型提供的Ҏ和属性?/span>
String.prototype.trim=function(text){...} //我们跟String对象d了一个trim()ҎQ?/span>
>原型对象的问?/span>
.原型对象省略了ؓ构造函C低参数这一l节Q结果所以的实例对象取得的实例值都是一LQ所?/span>原型对象最大问题就是由本n本质导成?/strong>?/span>
function Person(){}
Person p = new Person();
Person.prototype={
say:function(){
alert("hi");
}
}
p.say();
Person p1 = new Person();
Person p2 = new Person();
alert(p1.say==p2.say);//true
//所以接下来我们是?/span> 解决怎么合理׃n,卛_理用prototypeQ?/span>
>l合使用构造函数模式和原型模型(最常见的方?
.构造函数模式用于定义:实例属?可以传递多个参C保必要?
原型模式用于定义Q共享的属性和Ҏ(q样即保证了安全Q也保证了最大的节约内存)
例:function Person(name,age){
this.name=name;
this.age = age;
this.friend=["zhangsan","lisi","wangmazi"];
}
Person.prototype={
constructor:Person,
say:function(){
alert(this.name+" "+this.age);
}
}
Person p1 = new Person("xcp","23");
Person p2 = new Person("lxm","25");
alert(p1.friends==p2.friends);//false;
alert(p1.say==p2.say);//true;
.动态原型模?br /> function Person(name,age){
this.name=name;
this.age = age;
this.friend=["zhangsan","lisi","wangmazi"];
if(typeof this.say !="function"){
Person.prototype.say:function(){
alert(this.name+" "+this.age);
}
//再一ơ强调这不能写成
Person.prototype={...}
}
}
>寄生构造函数模?br /> .在工厂模式上加上参数
function Person(name,age){
var o = new Object();
o.name=name;
o.age = age;
o.say=function(){
alert(this.name+" "+this.age);
}
return o;
}
2.l承
一般所有的OO都支持接口承和实现l承Q而ECMAScript?span style="color: #000000">数没?/span>{明的说话(I函数标志或者说接口的声明方法)Q所以只有实现承,而实现承主要是通过原型对象来实C?nbsp;
>原型?/strong>(重要思想)
. 单回一下构造函敎ͼ原型和实例的关系
构造函数的prototype属?指针) -> 原型地址
原型的construtcotr属?指针) -> 构造函数地址
实例的_proto_属?内部指针) -> 原型对象
.原型铄思想
我们一个原型对象的指针指向另一个构造函数。如此层层递进Q就实现了实例和原型的链?br /> function SuperType(){
this.property = true;
}
SuperType.prototype.getSuperValue=function(){
return this.property;
}
function Subtype(){
this.subproperty = false;
}
SubType.prototype = new SuperType(); //子类的原型对象指向 生成的超cȝ子类Q所以有一个_proto_指针指向类的面型对象)
SubType.prototype.getSubValue=function(){
return this.subproperty;
}
Subtype instance = new Subtype();
instance.getSuperValue();
分析Q?br />
.如果我们调用subType.getSuperValue()l过的步骤有Q?Q搜索实例本w?2Q搜索SubType.prototype 3)搜烦SuperType.prototype 4)所有的c都是实现ObjectQ所以如果前面没有找到的话,p要搜索Object.prototype;所以真正的原型铑ֺ该是Q?br /> 
//再到q来q来一下,不是原型对象的constructor被重写了Q而且_proto_指针被重写了?br />
. 两种Ҏ来确定实现跟原理之间的关p?br /> //是否是指定类型的实现
alert(instance instanceof Object)//true;
alert(instance instanceof SuperType);//true;
alert(instance instanceof SubType);//true;
alert(instance instanceof Data); //false;
//指定cd的原型对象是否派生了此实?br /> alert(Object.prototype.isPrototype(instance));//true;
alert(SuperType.prototype.isPrototype(instance));//true;
alert(SubType.prototype.isProtoType(instance));//true
.重写类Ҏ
在SubType.prototype = new SuperType(); 后面d如下Q?br /> //重写类Ҏ
SubType.prototype.getSuperValue=function(){
return false;
}
//不能写成q样
SubType.prototype=new Supertype();
SubType.prototype={
getSuperValue=function(){
return false;
}
} //当一使用q一句话Ӟ上一句话qd效了Qؓ什么呢Q前面已l说q一q样切断了SubType与SuperType.prototype的链?br />
.原型铄问题
最主要的问题就是包含引用类型类型的?换一句就?strong style="color: red">讉K安全性问?/strong>Q怎么说来着Q前面介l包含引用类型值的原型属性民会被所有实例共享;而这也正是ؓ什么要在构造函CQ而不是在原型对象中定义属性的原因。但我们通过原型来实现承时Q原型实际上会变成另一个类型的实例Q于是,原先的实例属性和原型对象里面所有的属性和Ҏ利成章地变成了现在的原型属性了Q从而可以将属性工享这q坏了原有的安全性了?br />
>借用构造函?/strong>Q也叫伪造对象和l典l承->常用方式Q?br /> .无参数版
function SuperType(){
colors:["red","blue","green"];
}
function SubType(){
//实现l承SuperType,Z么呢Q因为在子类构造函数调用父cL造函数里面的callҎ
SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("block");
alert(instance1.colors); //"red","blue","green","block";
var instance2 = new SubType();
alert(instance2.colors); //"red","blue","green"
.有参数版
function SuperType(name){
this.name = name;
}
function SubType(){
//l承了SuperType,同时传递了参数
SuperType.call(this,"xcp");
//实例属?br /> this.age = 23;
}
var instance = new SubType();
alert(instance.name); //xcp
alert(instance.age); //23
.借用构造函数的问题
如果仅仅是借用构造函敎ͼ那么也将无法避免构造函数模式存在的问题Q方法都在构造函C定义Q这样些函数复用无从谈起了?br />
>l合l承(也称伪经典?,指的是将原型铑֒借用构造函数的技术结合在一hQ从而发挥者这宅的一U承模?br /> .实例(_օ实例)
function SuperType(name){
this.name = name;
this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName=function(){
alret(this.name);
}
function SubType(name,age){
//l承属?br /> SuperType.call(this,name);
//d新属?br /> this.age = age;
}
//l承原型里面的属性和Ҏ
SubType.prototype = new SuperType();
//d新方?br /> SubType.prototype.sayAge = function(){
alert(this.age);
}
var instance1 = new SubType("xcp",23);
instance1.colors.push("black");
alert(instance1.colors); //red,blue,green,black
instance1.sayName();//xcp;
instance1.sayAge();//23;
var instance2 = new SubType("lxm",25);
alert(instance2.colors); //red,blue,green
instance2.sayName();//lxm
instance2.sayAge(); //25
//l合l承避免了前面的原型链Q父cL有的属性和Ҏ均作用子cȝ原型对象的属性和ҎQ所以就存在数据安全问题了)和借用构造函数的~陷Q无׃n属性和Ҏ机制Q;成ؓJavascript中最常用的承模式。而且Qinstanceof和isPrototypeOf()也能够用于识别基于组合承创建的对象?br />
>当然q包括:原型式ѝ寄生式l承{?br />
3.ȝ
>创徏javascript对象的方?br /> .ҎQ?br /> 构造方法式<接收参数传值实例属?gt;+原型?lt;抽取公共׃n的方?gt;
.实例Q?br /> function Person(name,age){
this.name=name;
this.age = age;
this.friend=["zhangsan","lisi","wangmazi"];
}
Person.prototype={ //使用最对象完成
constructor:Person,
say:function(){
alert(this.name+" "+this.age);
}
}
Person p1 = new Person("xcp","23");
Person p2 = new Person("lxm","25");
alert(p1.friends==p2.friends);//false;
alert(p1.say==p2.say);//true;
>l承类的方?br /> .Ҏ
借用构造函数式<复用类的实例变量,表示不同实例得到不变量不?gt;+原型?lt;复用类的原型对象,意思就是子cȝ_proto_指针指同类的原型对?gt;
.实例
function SuperType(name){
this.name = name;
this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName=function(){
alret(this.name);
}
function SubType(name,age){
//l承属?br /> SuperType.call(this,name);
//d新属?br /> this.age = age;
}
//l承原型里面的属性和Ҏ
SubType.prototype = new SuperType();
//d新方?br /> SubType.prototype.sayAge = function(){
alert(this.age);
}
var instance1 = new SubType("xcp",23);
instance1.colors.push("black");
alert(instance1.colors); //red,blue,green,black
instance1.sayName();//xcp;
instance1.sayAge();//23;
var instance2 = new SubType("lxm",25);
alert(instance2.colors); //red,blue,green
instance2.sayName();//lxm
instance2.sayAge(); //25

]]>