JavaScript面向对象设计(2)

function SuperType() {
this.property =true;
}
SuperType.prototype.getSuperValue =function() {
    returnthis.property;
}
function SubType() {
    this.subproperty =false;
}
//发生继承行为
SubType.prototype =new SuperType();
SubType.prototype.getSubValue =function() {
    returnthis.subproperty;
}
var instance =new SubType();
alert(instance.getSuperValue()); //true
alert(instance instanceofObject); //true
alert(instance instanceof SuperType); //true
alert(instance instanceof SubType); //true
alert(Object.prototype.isPrototypeOf(instance)); //true
alert(SuperType.prototype.isPrototypeOf(instance)); //true
alert(SubType.prototype.isPrototypeOf(instance)); //true

代码中,重写了SubType的原型,而不是用原来默认的。由于property是一个实例属性,getSuperValue是一个原型方法。所以property会出现在SubType Prototype(SuperType的实例)中,而getSuperValue不会出现。instance的constructor现在只想的SuperType。

还有一个要提及的是,Javascript中,所有的函数默认的原型都是Object的实例,SuperType函数的prototype也是指向Object Prototype。 因此通过这样一个链条访问属性的时候,还是会通过搜索机制顺藤摸瓜的找到对应的属性。

原型链的缺点很明显,所有的子类的属性是共享的。这个缺点是致命的,因此实践中很少单独使用原型链。

call/apply方法这种方法称为constructor stealing(借用构造函数)。

call方法的作用,官方解释 call方法:

语法:call([thisObj[,arg1[, arg2[,  [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象。

说明: call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。 如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

我的理解,就是把原有对象中的代码,放到thisObj中运行,代码中如果出现this,代表的就是thisObj中。

举个例子:

function Animal(){ 
    this.name = "Animal"; 
    this.showName = function(){ 
        alert(this.name); 
    } 

/**定义一个Cat类*/ 
function Cat(){ 
    this.name = "Cat"; 

 
/**创建两个类对象*/ 
var animal = new Animal(); 
var cat = new Cat(); 
 
//通过call或apply方法,将原本属于Animal对象的showName()方法交给当前对象cat来使用了。 
//输入结果为"Cat" 
animal.showName.call(cat,","); 
//animal.showName.apply(cat,[]);

关于call和apply方法的概念,可以自行网上查阅,其中call和apply的差别在于调用时候的参数。 call调用时,参数为用逗号分隔的一组值,而apply调用的时候,参数为是一个数组,一个记忆方式为,C对应comma,A对应Array。 call的主要运用场景就是在面向对象值的模拟继承关系。

例子:

function SuperType(){
this.colors = ["red", "blue", "green"];
}
function SubType(){
//继承了SuperType
SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
var instance2 = new SubType();
alert(instance2.colors); //"red,blue,green"

代码中,通过call方法,在SubType中,借用了SuperType中的函数的代码,以此来为完善自己的属性。这就导致SubType中的实例都有了自己的colors属性。 这种方式可以在子类的构造方法调用中输入参数。

function SuperType(name)
{
this.name= name;
}
function SubType(){//继承了SuperType,并且传递了参数
SuperType.call(this,"zhangsan");
this.age=20;
}
var instance=new SubType();
alert(instance.name) //zhangsan
alert(instance.age) //20

当然,这种方式也存在缺点,方法都在构造函数中定义,并没有真正复用。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/c1954af2527bc56850352470470ecba6.html