原型模式

原型于in操作符
in操作符会在通过对象能够访问给定属性时返回true,无论该属性在实例中还是原型中。
function Person(){
Person.prototype.name='1';
Person.prototype.age='3';
Person.prototype.sayName=function(){
alert(this.name)
}
}
var person1=new Person();
'name' in person1 //true  原型中
person1.name='3';
'name' in person1 //true  实例中 
for in 返回所有能通过对象返回的属性。所有开发人员定义的属性都是可以enumerable的。
for(var c in person1){
console.log(c)
}
VM1348:2 name
VM1348:2 age
VM1348:2 sayName

Object.keys( )方法,接收一个对象,返回一个包含所有可枚举属性的字符串数组。
Object.keys(Person.prototype)//["name", "age", "sayName"] 返回一个字符串数组
Object.keys(person1) //[]  通过Person的实例调用方法,只返回该实例中的属性,所有返回一个空数组。

Object.getOwnPropertyNames() 方法。返回原型中所有可以枚举和不可枚举属性,该方法接收一个原型对象。

更简单的原型语法

用一个包含所有属性和方法的对象字面量来重写整个原型对象。

function Person(){
}
Person.prototype={
name:'2',
age:'3',
sayName:function(){alert(this.name)}
}
每次创建一个函数就会创建一个prototype对象,这个对象会自动获得constructor属性,这个属性会指向Person。而Person会有一个【prototype指针】,
我们重写了person.prototype,constructor不在指向Person,而是指向Object。可以将constructor设置为Person。但是这样会造成constructor特性为true,
变成可枚举了,可以definedProperty()方法修改默认数据属性。

A的原型P的constructor指向A,而C的原型P指向C,A的原型P,用C实例化后,P被重写,A的P指向C,通过A实例化Q,Q的constructor指向C

继承
面向对象语言OO支持两种继承方式,接口继承和实现继承,javascript是实现继承,实现继承则继承实际的方法,实现继承主要依靠原型链来实现的。
function superType(){   //每个函数会创建一个prototype对象,prototype对象有一个constructor属性,该属性指向superType。
this.property=true;
}
//给该函数原型添加一个方法
superType.prototype.getSuperValue=function(){
return this.property;                              
}
//创建一个新函数
function subType(){
this.subproperty=false;
}
//继承
subType.prototype=new superType();  subType的原型继承了superType。也就subType的原型是superType的实例。
//给subType的原型添加一个方法
subType.prototype.getSubValue=function(){
return this.subproperty;
}
var instance=new subType()// 实例化一个对象
instance.getSuperValue  //treun    先搜索实例有没有这个属性,然后搜索subtype原型,之后搜索supertype原型。

注意!给subtype原型添加方法,要在subtype实例原型替换后添加,如果在原型没有替换之前添加方法,给方法将别移除,因为替换的时候重写了prototype。

可以说instance是subtype supertype object的实例。
subtype的原型prototype指向supertype的原型,superType的prototype指向object。本来subtype的原型constructor指向subtype,因为supertype实例化了subtype的原型,constructor也被重写,指向了supertype。

原型模式多用于定义方法和共享属性,构造函数多用于定义实例属性。

借用构造函数
在子类型构造函数调用超类类型构造函数,使用apply()和call()方法可以在新创建的对象上执行构造函数。

function SuperType(){
this.colors=['blue','gray','red'];
}

function SubType(name){
SuperType.call(this);   //子类型继承超类型属性
this.name='Ma'
}
var instance=new SubType();var instance.colors.push('pink') // length 4 var instance1=new SubType();instance1.colors.length //3 子类型共享超类型属性,但是实例不能共享同一个对象的实例。也就子类型看不到超类型原型中定义的方法,结果就是所有类型只能使用构造函数模式。
借用构造函数有一个很大的优势,是可以对超类型传递参数。function SuperType(name){
this.name=name;
}function SubType(name){
SuperType.call(this,name); //call()为超类型传递参数
}var instance=new SupType('cai');instance.name //cai 为了确保超类型构造函数不会重写子类型,请在调用超类型后再为子类型添加属性。
组合继承

组合继承有时候也叫做伪经典继承,将原型链和借用构造函数的技术合到一块,使用原型链实现对原型属性和方法的继承,借用构造函数来实现对实例属性的继承。
function SuperType(name){
this.name=name;
this.colors=['red','yellow','gray'];
}

SuperType.prototype.getSuperValue=function(){
alert(this.name);
}

function SubType(name){           构造函数在调用超类,传入name参数(子类拥有了超类属性),之后要定义了自己属性age。
SuperType.call(this,name);
this.age='23';
}                                 //借用构造函数
SubType.prototype=new SuperType()   //原型替换,Sub的原型被重写,重写后拥有Super的属性及原型方法。sub的原型变成了super的实例。
SubType.prototype.constructor=SubType   //增强对象,弥补因重写原型而失去的默认constructor属性。
SubType.prototype.sayName=function(){       
alert(this.age)
}
var instance1=new SubType('cai');     
instance1.colors.push('blue');
instance1.colors.length  //4
var instance2=new SubType('Ma');
instance2.getSuperValue(); //Ma          
这样就让两个不同的Super实例拥有自己的属性。instanceof也可以识别它们基于组合继承创建对象
原型试继承
function object(o){      //每次给原型添加属性,要么实例化,要么prototype.添加。
function F(){}           //通过这个函数,我们直接将对象传入该函数,会返回一个临时实例,实例原型就是我们传入的对象。把不变的东西封装起来。
F.prototype=o;
return new F();
}
var Person={name:'cai',colors:['red','green','blud']};
var Person1=object(Person);
Person1.name    //cai             
要求你必须有一个对象可以作为另一个对象的基础,将person作为另一个对象的基础,传入object。返回一个新对象,person作为新对象的原型。
ECMAScript 5 Object.create()方法规范了原型式继承。这个方法接收两个参数:一个是作为新对象原型的对象和(可选)一个新对象定义额外属性的对象。
var Person={name:'cai',
colors:['red','green','blud']};
var create1=Object.create(Person);
create.name  //cai
Object.create()的第二个参数与Object.definedProperties()第二个参数格式相同。
var create2=Object.create(Person,{name:{value:22}});
create2.name //22         

寄生式继承
寄生继承的思路,创建一个仅用于封装继承过程的函数,该函数在内部已某种方式来增强对象。

function createAnother(o){
var clone=object(o);
clone.sayName=function(){
alert(hi);
}
return clone;
}
var Person={name:'cai',colors:['red','green','blud']};
var instance1=createAnother(Person) 返回一个新对象,不仅具有person的方法也有自己的方法sayName
寄生组合继承
function SuperType(name){
this.name=name;
this.colors=['blue','green','gray'];        
}
function SubType(name){
SuperType.call(this,name);  //第二次调用super
this.age=22;
}
SubType.prototype=new SuperType();   //第一次调用super
组合继承的缺点就是调用了两次超类型,而寄生组合继承解决了这个问题
function inheritProperty(SubType,SuperType){
var prototype=object(SuperType.prototype);   //传入SuperType原型,返回一个新对象prototype
prototype.constructor=SubType;
Subtype.prototype=prototype;               //重写SubType原型,指定对象
}

function SubType(name){
SuperType.call(this,name); 
this.age=22;
}
inheritProperty(SubType,SuperType); 通过寄生组合继承,只调用了一次superType().

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值