欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

原型模式学习之原型于in操作符、原型语法等知识点讲解

程序员文章站 2022-06-10 22:10:38
原型于in操作符 in操作符会在通过对象能够访问给定属性时返回true,无论该属性在实例中还是原型中。 function person(){ person.prototype.name=...

原型于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().