设为首页 加入收藏

TOP

JavaScript面向对象设计(二)
2017-02-08 08:16:44 】 浏览:392
Tags:JavaScript 面向 对象 设计
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。


还有一个要提及的是,java script中,所有的函数默认的原型都是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


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


function SuperType(){
this.colors = ["red", "blue", "green"];
this.sayHi=function(){console.log("Hi")};
}
function SubType(){
//继承了SuperTypeSuperType.call(this);
}
var instance1 = new SubType();
var instance2 = new SubType();
alert(instance1.sayHi==instance2.sayHi); //false


组合继承原型链和call方式都有缺点,但是把两者取长补短,形成组合继承。其思想非常简单,用原型链方式,对需要共享的原型属性和方法实现继承。再通过call方式借用构造函数来实现无需共享的属性的继承。这样即有了共享的属性,也有了不共享的属性。


function SuperType(name) {
? ? this.name = name;
? ? this.colors = ["red", "blue", "green"];
}
//sayName能够被共享
SuperType.prototype.sayName = function() {
? ? alert(this.name);
};
?
function SubType(name, age) {
? ? //继承属性
?call方式继承 ,name属性不会被共享
? ? SuperType.call(this, name);
? ? this.age = age;
}
?
//继承方法 原型链方式继承
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function() {
? ? alert(this.age);
};
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
instance1.sayName(); //"Nich

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇GC.Collect如何影响垃圾回收 下一篇Java Garbage Collection基础之Ja..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目