我几乎不了解C#,现在我开始使用JavaScript
,但在理解基本原理时遇到了一些问题。
这是我的代码示例:
function BaseFunc(x, y) {
this.X = x;
this.Y = y;
}
function DerivedFunc(x, y, z) {
this.Z = z;
BaseFunc.call(this, x, y);
}
DerivedFunc.prototype = new BaseFunc;
function Test() {
var d = DerivedFunc(1, 2, 3);
var b = new BaseFunc(4, 5);
d.sayHello();
b.sayHello();
}
DerivedFunc.prototype.sayHello = function () {
alert("Result is: " + (this.X + this.Y + this.Z));
}
在上面的代码中,我试图进行继承。
一切看起来都很好,直到我到达
BaseFunc.call(this, x, y);
行,该行应该调用基本函数,但是this
在此上下文中的用途是什么。只是为了满足方法
call
的签名,它是如何工作的?第二个问题是,在javascript中,我们可以动态添加任何内容,
就我而言,我要添加一个
sayHello()
属性,并为其分配一个匿名函数。像
DerivedFunc.prototype.sayHello
一样,我是向BaseFunc
还是DerivedFunc
添加属性/方法,因为它是添加到原型中的,所以应理解为应该添加到BaseFunc
中。但是当我执行上面的代码时,我得到未定义sayHello
的错误。有人可以向我说明发生了什么问题吗,谢谢?
最佳答案
一切都很好,直到我到达BaseFunc.call(this,x,y);行为止。该行应该调用基本函数,但是在此上下文中此函数的用途是什么。
在那里,在对BaseFunc
的调用中,this
与在对DerivedFunc
的调用中具有相同的值,因此this.X = x;
等行在BaseFunc
中被分配给正确的实例。 (调用函数为this
设置特定值就是函数的.call
和.apply
方法执行的操作。)
但是,当我执行上面的代码时,我得到错误,没有定义sayHello。
如果问题出在d.sayHello
上,那是因为您错过了new
行上的d = DerivedFunc(1, 2, 3);
运算符。由于DerivedFunc
仅作为函数而不通过new
调用时,没有任何返回值,因此d
将为undefined
。
请注意,您进行继承的方式虽然很常见,但却存在问题。主要问题在这里:
DerivedFunc.prototype = new BaseFunc;
您正在尝试使用旨在创建实例并接受参数的函数,以创建将
DerivedFunc
分配给事物的原型实例。那么BaseFunc
应该如何处理缺少的参数?然后,稍后(从DerivedFunc
)再次调用它以初始化实例。 BaseFunc
正在执行双重任务。以下是纠正方法,首先是冗长的版本:
function x() { }
x.prototype = BaseFunc.prototype;
DerivedFunc.prototype = new x;
DerivedFunc.prototype.constructor = DerivedFunc;
或者,如果您可以依靠ES5的
Object.create
:DerivedFunc.prototype = Object.create(BaseFunc.prototype);
DerivedFunc.prototype.constructor = DerivedFunc;
现在我们不调用
BaseFunc
来创建原型,但是我们仍在获取其prototype
对象作为DerivedFunc
的prototype
对象的基础原型。我们不再遇到与BaseFunc
的参数有关的问题,并且仅以被设计为被调用的方式调用BaseFunc
:初始化单个实例,而不初始化原型。自然,与其每次都想派生构造函数时都编写它,不如为其提供一个帮助程序脚本。
如果您对JavaScript继承层次结构感兴趣,则可能需要查看我的简短
Lineage
脚本-不一定要使用,而是要了解这些工作原理。 page showing how to do things without the script以及与使用脚本进行比较可能特别有用。关于javascript - 需要对Javascript进行基本澄清,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20630605/