硬性编码的Solution:
让我们看一下第一个例子,它采用了标准的原型化方式,但问题是:它的子类方法如何调用父类(基类)方法?下面是一些开发者尝试并采用的方式:
一种企图进行父类调用的“通病”:
function BaseClass() { } BaseClass.prototype.getName = function() { return "BaseClass(" + this.getId() + ")"; }
BaseClass.prototype.getId = function() { return 1; }
function SubClass() {} SubClass.prototype = new BaseClass(); SubClass.prototype.getName = function() { //调用父类的getName()方法 //哈哈,这是对父类调用的直接引用吗? return "SubClass(" + this.getId() + ") extends " + BaseClass.prototype.getName(); }
SubClass.prototype.getId = function() { return 2; }
//输出结果:"SubClass(2) extends BaseClass(1)"; //这是正确的输出吗? alert(new SubClass().getName());
上面的代码是对第一段脚步进行修改后的版本,我去掉了一些注释和空格,使你能注意到新的getId()方法和对父类的调用。你一定急于知道通过这样对BaseClass的硬性编码引用(hard coded reference),它是否能进行正确地调用BaseClass的方法?
一个正确的、多态的父类调用必做的事情是保证“this”引用指向当前对象实例和类方法。在这里,看上去和它应该输出的结果非常接近,看上去好像在SubClass中调用了BaseClass的getName()方法。你发现问题了吗?这个问题是非常细小的,但却很重要决不能忽视。通过使用上面的父类调用语法,BaseClass的getName()方法被调用,它返回一个字符串:包括类名和“this.getId()”的返回值。问题在于“this.getId()”应该返回2,而不是1。如果这和你所想的不同,你可以查看Java或者C#这类OO语言的多态性。
改进后的硬性编码Solution:
你可以通过一个微小的改动来解决这个问题。
静态(硬编码)父类调用:
function BaseClass() { } BaseClass.prototype.getName = function() { return "BaseClass(" + this.getId() + ")"; }
BaseClass.prototype.getId = function() { return 1; }
function SubClass() {} SubClass.prototype = new BaseClass(); SubClass.prototype.getName = function() { //一点魔法加上多态性! //但很明显,这还是一个直接引用! return "SubClass(" + this.getId() + ") extends " + BaseClass.prototype.getName.call(this); }
SubClass.prototype.getId = function() { return 2; }
//输出结果:"SubClass(2) extends BaseClass(2)"; //Hey, 我们得到了正确的输出! alert(new SubClass().getName());
在 ECMA-262 JavaScript/EcmaScript标准 中,Call()方法是所有Function实例的一个成员方法,这已经被所有的主流浏览器所支持。JavaScript把所有的function看作对象,因此每个function都具有方法和附着其上的属性。Call()方法允许你调用某个function,并在function的调用过程中确定“this”变量应该是什么。JavaScript的function没有被紧紧地绑定到它所在的对象上,所以如果你没有显式地使用call()方法,“this”变量将成为function所在的对象。
另外一种方法是使用apply方法,它和call()方法类似,只在参数上存在不同:apply()方法接受参数的数组,而call()方法接受单个参数。
 
说明:本教程来源互联网或网友上传或出版商,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。
2/2 首页 上一页 1 2 |