每天一篇javascript学习小结(面向对象编程)
1、面向对象的工厂方法
functioncreatePerson(name,age,job){
varo=newObject();
o.name=name;
o.age=age;
o.job=job;
o.sayName=function(){
alert(this.name);
};
returno;
}
varperson1=createPerson("Nicholas",29,"SoftwareEngineer");
varperson2=createPerson("Greg",27,"Doctor");
person1.sayName();//"Nicholas"
person2.sayName();//"Greg"
工厂模型的方法的缺点是会产生大量重复代码!
2、构造函数模式创建对象
functionPerson(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.sayName=function(){
alert(this.name);
};
}
varperson1=newPerson("Nicholas",29,"SoftwareEngineer");
varperson2=newPerson("Greg",27,"Doctor");
person1.sayName();//"Nicholas"
person2.sayName();//"Greg"
alert(person1instanceofObject);//true
alert(person1instanceofPerson);//true
alert(person2instanceofObject);//true
alert(person2instanceofPerson);//true
alert(person1.constructor==Person);//true
alert(person2.constructor==Person);//true
alert(person1.sayName==person2.sayName);//false
使用new关键字创建对象会经历以下四个过程
- 1、创建一个新对象
- 2、将构造函数的作用域赋给一个新对象(因此this就指向了这个新对象)
- 3、执行构造函数的方法(为这个新对象赋值)
- 4、返回新对象
3、将构造函数当函数用
functionPerson(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.sayName=function(){
alert(this.name);
};
}
varperson=newPerson("Nicholas",29,"SoftwareEngineer");
person.sayName();//"Nicholas"
Person("Greg",27,"Doctor");//addstowindow
window.sayName();//"Greg"
varo=newObject();
Person.call(o,"Kristen",25,"Nurse");
o.sayName();//"Kristen"
构造函数当做函数使用就和普通的函数没有任何不同,它属于window对象下面添加的方法而已。由于构造函数创建的对象实际上是创建一个新对象,因此在本质上两者还是不一样的,还是分离的,他们的方法还是不一样的!
4、将共有的方法方法全局解决不一致的问题
functionPerson(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.sayName=sayName;
}
functionsayName(){
alert(this.name);
}
varperson1=newPerson("Nicholas",29,"SoftwareEngineer");
varperson2=newPerson("Greg",27,"Doctor");
person1.sayName();//"Nicholas"
person2.sayName();//"Greg"
alert(person1instanceofObject);//true
alert(person1instanceofPerson);//true
alert(person2instanceofObject);//true
alert(person2instanceofPerson);//true
alert(person1.constructor==Person);//true
alert(person2.constructor==Person);//true
alert(person1.sayName==person2.sayName);//true
虽然上面的方法解决了一致的问题,但是定义的全局的方法本身属于window,那么局部和全局就没有分开!所以这个方法使用的并不多见!也不建议使用。
5、原型模式
我们创建的任何的一个函数都有一个原型对象,这个属性是一个指针,它指向一个对象,而这个对象的作用是可以有特定的类型的所有的实例共享的方法!
functionPerson(){
}
Person.prototype.name="Nicholas";
Person.prototype.age=29;
Person.prototype.job="SoftwareEngineer";
Person.prototype.sayName=function(){
alert(this.name);
};
varperson1=newPerson();
person1.sayName();//"Nicholas"
varperson2=newPerson();
person2.sayName();//"Nicholas"
alert(person1.sayName==person2.sayName);//true
alert(Person.prototype.isPrototypeOf(person1));//true
alert(Person.prototype.isPrototypeOf(person2));//true
//onlyworksifObject.getPrototypeOf()isavailable
if(Object.getPrototypeOf){
alert(Object.getPrototypeOf(person1)==Person.prototype);//true
alert(Object.getPrototypeOf(person1).name);//"Nicholas"
}
理解原型
无论什么时候只要是创建了一个函数,就会创建一个原型属性,这个属性指向函数的原型对象。在默认的情况下,原型对象都会包含一个constructor(构造函数属性),这个属性包含一个指向prototype属性所在函数的指针!
属性读取的顺序
每当代码读取某个对象的属性时候,都会执行一次搜索,目标是具有给定名字的属性,搜索从对象的实例本身开始查找,如有则返回,没有则继续搜索该对象的原型链,直至搜索到原型链的最外层!
functionPerson(){
}
Person.prototype.name="Nicholas";
Person.prototype.age=29;
Person.prototype.job="SoftwareEngineer";
Person.prototype.sayName=function(){
alert(this.name);
};
varperson1=newPerson();
varperson2=newPerson();
person1.name="Greg";
alert(person1.name);//"Greg"来自实例
alert(person2.name);//"Nicholas"来自原型
如果删除了这个元素的实例属性
functionPerson(){
}
Person.prototype.name="Nicholas";
Person.prototype.age=29;
Person.prototype.job="SoftwareEngineer";
Person.prototype.sayName=function(){
alert(this.name);
};
varperson1=newPerson();
varperson2=newPerson();
person1.name="Greg";
alert(person1.name);//"Greg"?frominstance
alert(person2.name);//"Nicholas"?fromprototype
deleteperson1.name;
alert(person1.name);//"Nicholas"-fromtheprototype
6、hasOwnProperty方法
这个方法可以检测一个属性是否存在于实例中,还是存在于原型中!hasOwnProperty是从Object继承来的,只要给定属性存在于对象实例中,才会返回true.
functionPerson(){
}
Person.prototype.name="Nicholas";
Person.prototype.age=29;
Person.prototype.job="SoftwareEngineer";
Person.prototype.sayName=function(){
alert(this.name);
};
varperson1=newPerson();
varperson2=newPerson();
alert(person1.hasOwnProperty("name"));//false
alert("name"inperson1);//true
person1.name="Greg";
alert(person1.name);//"Greg"?frominstance
alert(person1.hasOwnProperty("name"));//true
alert("name"inperson1);//true
alert(person2.name);//"Nicholas"?fromprototype
alert(person2.hasOwnProperty("name"));//false
alert("name"inperson2);//true
deleteperson1.name;
alert(person1.name);//"Nicholas"-fromtheprototype
alert(person1.hasOwnProperty("name"));//false
alert("name"inperson1);//true
7、Object.keys()可枚举属性方法
这个方法接收一个对象作为参数,返回一个包含所有可枚举属性的字符串数组
functionPerson(){
}
Person.prototype.name="Nicholas";
Person.prototype.age=29;
Person.prototype.job="SoftwareEngineer";
Person.prototype.sayName=function(){
alert(this.name);
};
varkeys=Object.keys(Person.prototype);
alert(keys);//"name,age,job,sayName"
如果想得到所有实例的属性,无论它是否可以枚举都可以使用这个方法来获取
functionPerson(){
}
Person.prototype.name="Nicholas";
Person.prototype.age=29;
Person.prototype.job="SoftwareEngineer";
Person.prototype.sayName=function(){
alert(this.name);
};
varkeys=Object.getOwnPropertyNames(Person.prototype);
alert(keys);//"constructor,name,age,job,sayName"
此方法高版本浏览器才支持
8、简单的原型写法
functionPerson(){
}
Person.prototype={
name:"Nicholas",
age:29,
job:"SoftwareEngineer",
sayName:function(){
alert(this.name);
}
};
varfriend=newPerson();
alert(friendinstanceofObject);//true
alert(friendinstanceofPerson);//true
alert(friend.constructor==Person);//false
alert(friend.constructor==Object);//true
重写了原型就等于将默认的原型方法覆盖,那么同样的构造方法也会被重写,重写的构造方法指向了Object对象!而不是原来的对象Person
如果还是想指向之前的构造方法,可以显示的指定
functionPerson(){
}
Person.prototype={
constructor:Person,
name:"Nicholas",
age:29,
job:"SoftwareEngineer",
sayName:function(){
alert(this.name);
}
};
varfriend=newPerson();
alert(friendinstanceofObject);//true
alert(friendinstanceofPerson);//true
alert(friend.constructor==Person);//true
alert(friend.constructor==Object);//false
9、原型方法的动态添加
functionPerson(){
}
Person.prototype={
constructor:Person,
name:"Nicholas",
age:29,
job:"SoftwareEngineer",
sayName:function(){
alert(this.name);
}
};
varfriend=newPerson();
Person.prototype.sayHi=function(){
alert("hi");
};
friend.sayHi();//"hi"?works!
10、原生对象的原型方法
alert(typeofArray.prototype.sort);//"function"
alert(typeofString.prototype.substring);//"function"
String.prototype.startsWith=function(text){//修改原生对象的原型方法
returnthis.indexOf(text)==0;
};
varmsg="Helloworld!";
alert(msg.startsWith("Hello"));//true
11、组合使用构造函数和原型模式创建对象
//构造函数模式
functionPerson(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.friends=["Shelby","Court"];
}
//原型模式
Person.prototype={
constructor:Person,
sayName:function(){
alert(this.name);
}
};
varperson1=newPerson("Nicholas",29,"SoftwareEngineer");
varperson2=newPerson("Greg",27,"Doctor");
person1.friends.push("Van");
alert(person1.friends);//"Shelby,Court,Van"
alert(person2.friends);//"Shelby,Court"
alert(person1.friends===person2.friends);//false
alert(person1.sayName===person2.sayName);//true
12、动态原型模式
functionPerson(name,age,job){
//properties
this.name=name;
this.age=age;
this.job=job;
//methods
if(typeofthis.sayName!="function"){
Person.prototype.sayName=function(){
alert(this.name);
};
}
}
varfriend=newPerson("Nicholas",29,"SoftwareEngineer");
friend.sayName();
13、寄生构造函数模式
functionPerson(name,age,job){
varo=newObject();//依赖全局对象初始化一个对象,然后再返回这个对象
o.name=name;
o.age=age;
o.job=job;
o.sayName=function(){
alert(this.name);
};
returno;
}
varfriend=newPerson("Nicholas",29,"SoftwareEngineer");
friend.sayName();//"Nicholas"
functionSpecialArray(){
//createthearray
varvalues=newArray();
//addthevalues
values.push.apply(values,arguments);
//assignthemethod
values.toPipedString=function(){
returnthis.join("|");
};
//returnit
returnvalues;
}
varcolors=newSpecialArray("red","blue","green");
alert(colors.toPipedString());//"red|blue|green"
alert(colorsinstanceofSpecialArray);
上诉方法有一点说明下,由于它是依赖外层对象来创建一个新对象,因此不能依赖instanceof方法来确定属性和方法的来源!它实际上和构造函数的没有关系!
14、稳妥构造函数模式
functionPerson(name,age,job){
varo=newObject();
o.sayName=function(){
alert(name);
};
returno;
}
varfriend=Person("Nicholas",29,"SoftwareEngineer");
friend.sayName();//"Nicholas"
此方法不依赖任何newthis关键符!如果要访问对象的方法和属性,只能通过对象已经定义好的方法来获取!
15、继承
javascript实现继承是通过原型链来实现的
functionSuperType(){
this.property=true;//定义一个属性
}
SuperType.prototype.getSuperValue=function(){//定义的原型方法
returnthis.property;
};
functionSubType(){
this.subproperty=false;
}
//inheritfromSuperType
SubType.prototype=newSuperType();
SubType.prototype.getSubValue=function(){
returnthis.subproperty;
};
varinstance=newSubType();
alert(instance.getSuperValue());//true
alert(instanceinstanceofObject);//true
alert(instanceinstanceofSuperType);//true
alert(instanceinstanceofSubType);//true
alert(Object.prototype.isPrototypeOf(instance));//true
alert(SuperType.prototype.isPrototypeOf(instance));//true
alert(SubType.prototype.isPrototypeOf(instance));//true
SubType继承SuperType的方法和属性,因此当instance可以直接调用SuperType的方法!
functionSuperType(){
this.property=true;
}
SuperType.prototype.getSuperValue=function(){
returnthis.property;
};
functionSubType(){
this.subproperty=false;
}
//inheritfromSuperType
SubType.prototype=newSuperType();
//newmethod
SubType.prototype.getSubValue=function(){
returnthis.subproperty;
};
//overrideexistingmethod
SubType.prototype.getSuperValue=function(){
returnfalse;
};
varinstance=newSubType();
alert(instance.getSuperValue());//false
上面的例子说明,重写的原型会覆盖之前继承的原型,最后返回的往往不是预期的效果
functionSuperType(){
this.property=true;
}
SuperType.prototype.getSuperValue=function(){
returnthis.property;
};
functionSubType(){
this.subproperty=false;
}
//inheritfromSuperType
SubType.prototype=newSuperType();
//使用字面量添加的方法导致上面的方法失效了
SubType.prototype={
getSubValue:function(){
returnthis.subproperty;
},
someOtherMethod:function(){
returnfalse;
}
};
varinstance=newSubType();
console.log(instance);
alert(instance.getSuperValue());//error!
下面的例子也说明重写原型带来的风险
functionSuperType(){
this.colors=["red","blue","green"];
}
functionSubType(){
}
//inheritfromSuperType
SubType.prototype=newSuperType();
varinstance1=newSubType();
instance1.colors.push("black");
alert(instance1.colors);//"red,blue,green,black"
varinstance2=newSubType();
alert(instance2.colors);//"red,blue,green,black"
原型共享导致两个不同的对象调用的同一个数据
16、借用构造函数来实现继承
functionSuperType(){
this.colors=["red","blue","green"];
}
functionSubType(){
//inheritfromSuperType
SuperType.call(this);
}
varinstance1=newSubType();
instance1.colors.push("black");
alert(instance1.colors);//"red,blue,green,black"
varinstance2=newSubType();
alert(instance2.colors);//"red,blue,green"
传递参数
functionSuperType(name){
this.name=name;
}
functionSubType(){
//inheritfromSuperTypepassinginanargument
SuperType.call(this,"Nicholas");
//instanceproperty
this.age=29;
}
varinstance=newSubType();
alert(instance.name);//"Nicholas";
alert(instance.age);//29
17、组合继承方式
functionSuperType(name){
this.name=name;
this.colors=["red","blue","green"];
}
SuperType.prototype.sayName=function(){
alert(this.name);
};
functionSubType(name,age){
SuperType.call(this,name);
this.age=age;
}
18、原型继承
functionobject(o){
functionF(){}
F.prototype=o;
returnnewF();
}
varperson={
name:"Nicholas",
friends:["Shelby","Court","Van"]
};
varanotherPerson=object(person);
anotherPerson.name="Greg";
anotherPerson.friends.push("Rob");
19、寄生组合式继承
functionobject(o){
functionF(){}
F.prototype=o;
returnnewF();
}
functioninheritPrototype(subType,superType){
varprototype=object(superType.prototype);//createobject
prototype.constructor=subType;//augmentobject
subType.prototype=prototype;//assignobject
}
functionSuperType(name){
this.name=name;
this.colors=["red","blue","green"];
}
SuperType.prototype.sayName=function(){
alert(this.name);
};
functionSubType(name,age){
SuperType.call(this,name);
this.age=age;
}
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge=function(){
alert(this.age);
};
varinstance1=newSubType("Nicholas",29);
instance1.colors.push("black");
alert(instance1.colors);//"red,blue,green,black"
instance1.sayName();//"Nicholas";
instance1.sayAge();//29
varinstance2=newSubType("Greg",27);
alert(instance2.colors);//"red,blue,green"
instance2.sayName();//"Greg";
instance2.sayAge();//27
以上就是今天的javascript学习小结,之后每天还会继续更新,希望大家继续关注。