从继承类的函数调用父函数
call parent ctor from ctor of inheriting class
是否可以不这样做
function Animal(name, numLegs) {
this.name = name;
this.numLegs = numLegs;
}
Animal.prototype.sayName = function() {
console.log("Hi my name is " + this.name);
};
function Penguin(name) {
this.name = name;
this.numLegs = 2;
}
Penguin.prototype = new Animal();
var penguin = new Penguin("Tux");
penguin.sayName();
呢?
function Animal(name, numLegs) {
this.name = name;
this.numLegs = numLegs;
}
Animal.prototype.sayName = function() {
console.log("Hi my name is " + this.name);
};
function Penguin(name) {
return new Animal(name, 2);
}
Penguin.prototype = new Animal();
var penguin = new Penguin("Tux");
penguin.sayName();
我发现第二个版本更优雅,并希望两个版本的结果相同,但对于第二个版本,codeacademy告诉我
Oops, try again. Make sure to create a new Penguin instance called penguin!
这不是调用父类构造函数的正确方法:
function Penguin(name) {
return new Animal(name, 2);
}
正确的方法如下:
function Penguin(name) {
Animal.call(this, name, 2);
}
原因在于new
的工作方式:
- 假设您有一个名为
ABC
的函数。 - 当你执行
new ABC
时,JavaScript创建一个ABC.prototype
的实例,并将其绑定到ABC
函数中的this
,这就是为什么你可以在ABC
中添加this
的属性。 - 构造函数默认返回
this
,除非你显式返回另一个对象。
Codecademy抱怨你的代码的原因是因为你返回的new Animal(name, 2)
是而不是和instanceof
Penguin
。
正如我之前所说的,调用父构造函数的正确方法是使用ParentConstructor.call(this, arg1, arg2, ...)
。在本例中,我们将父构造函数中的this
设置为与当前构造函数(即由new
创建的实例)中的this
相同的值。
如果你想写出优雅的代码,那么试试size:
function defclass(prototype) {
var constructor = prototype.constructor;
var instance = prototype.instance = function () {};
constructor.prototype = instance.prototype = prototype;
return constructor;
}
function extend(parent, keys) {
var supertype = keys.super = parent.prototype;
var prototype = new supertype.instance;
for (var key in keys) prototype[key] = keys[key];
return defclass(prototype);
}
使用defclass
和extend
你可以重写你的代码如下:
var Animal = defclass({
constructor: function (name, numLegs) {
this.name = name;
this.numLegs = numLegs;
},
sayName: function () {
console.log("Hi my name is " + this.name);
}
});
var Penguin = extend(Animal, {
constructor: function (name) {
this.super.constructor.call(this, name, 2);
}
});
var penguin = new Penguin("Tux");
penguin.sayName();
多酷啊?
我认为区别在于构造函数不返回值。所以如果你调用
new Penguin('bla')
不是企鹅函数返回新对象,而是new返回新对象。因此,如果您让Penguin()返回一个新对象,这将与new-keyword冲突。
如果你想调用父构造函数,你可以这样做:
function Penguin(name) {
Animal.call(this, name, 2);
}
还有一点:当你把Animal的原型赋值给它的子原型Penguin时,你在你的例子中调用了不带参数的函数。有一种更简洁的方法:
Penguin.prototype = Object.create(Animal.prototype);
之后,您已经丢失了Penguin的构造函数,因此您需要像这样重新分配它:
Penguin.prototype.constructor = Animal;
详细说明如下:https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript
和https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript
在第二个例子中,您返回的不是Penguin的实例,而是Animal的实例。如果你想给企鹅添加更多的功能,你需要用额外的功能来装饰Animal类。
function Penguin(name) {
var self = new Animal(name, 2);
self.penguinFunction = function (){
//do something here
}
return self;
}
- 如何使jQuery插件函数可调用以供独立使用,而不在集合上操作
- Meteor Router数据函数被调用两次
- 拦截对构造函数的调用
- 为什么(如何)'这'从函数内部调用回调时发生更改
- 比较sessionStorage值时,Javascript函数无法调用
- 如何从构造函数中调用js原型方法
- 使用AJAX将变量发布到不同文件上的php函数并调用该函数
- 从构造函数es6调用静态方法
- 如何在函数中调用函数?(CoffeeScript)
- 我在画布中的鼠标按下函数在调用时不会重绘背景
- Javascript 从函数名称调用函数
- 使用函数按钮调用 ajaxform
- 调用子类函数时调用的超类函数
- 如何使用字符串作为类名并在函数中调用它
- 轮询 ajax 函数超出调用堆栈
- java-script 函数被调用两次
- 使用 Promise 在另一个函数中调用带有 Bluebird 承诺库的函数
- 更改函数名称调用中的单击事件
- 使用promise或setTimeout确定延迟函数的调用顺序
- 如何避免在函数中调用函数