Javascript 如何实现类声明上的伪经典继承权?
注意: 正如答案所表明的,由于问题和我的评论中描述的一些问题,问题中提出的代码并没有真正实现继承(否则它将成为一个答案而不是一个问题…)。它的工作原理与预期一样,是继承的伪继承(甚至不是原型)Javascript 如何实现类声明上的伪经典继承权?,javascript,inheritance,types,prototype,Javascript,Inheritance,Types,Prototype,注意: 正如答案所表明的,由于问题和我的评论中描述的一些问题,问题中提出的代码并没有真正实现继承(否则它将成为一个答案而不是一个问题…)。它的工作原理与预期一样,是继承的伪继承(甚至不是原型) 摘要 简言之,使其与我们编写的通用OO语言(而不是javascript)类似,但保持继承正确 故事 是实现原型遗传的好方法,但对于类型的大脑和新的粉丝来说,这有点让人困惑 我们可以通过多种方式编写javascript代码,就像使用伪经典模式编写其他OO语言一样。由于它是伪经典的,我们必须正确处理jav
- 摘要 简言之,使其与我们编写的通用OO语言(而不是javascript)类似,但保持继承正确
- 故事
是实现原型遗传的好方法,但对于类型的大脑和新的粉丝来说,这有点让人困惑
我们可以通过多种方式编写javascript代码,就像使用伪经典模式编写其他OO语言一样。由于它是伪经典的,我们必须正确处理javascript的底层原型继承
我想找到的是一种方法,可以在类声明上实现伪经典继承。演示代码放在帖子的后面,它可以正常工作,但是,有一些恼人的事情:
- 我无法在类声明中删除
,否则继承将不起作用return
- 除了在类声明中传递
之外,我没有其他方法使返回的闭包知道什么是this
this
- 我还想去掉
,但还没有一个好主意函数(例如,_super){
- 类的静态(自身属性)不会被继承
一个解决方案比现有的框架更需要一些语法上的糖分,一个好的模式是适用的 - 我无法在类声明中删除
\u扩展了
功能:
function _extends(baseType) {
return function (definition) {
var caller=arguments.callee.caller;
var instance=this;
if(!(instance instanceof baseType)) {
(caller.prototype=new baseType()).constructor=caller;
instance=new caller();
}
var _super=function () {
baseType.apply(instance, arguments);
};
definition(instance, _super);
return instance;
};
}
Abc
课程:
function Abc(key, value) {
return _extends(Object).call(this, function (instance, _super) {
instance.What=function () {
alert('What');
};
instance.getValue=function () {
return 333+Number(value);
};
instance.Value=instance.getValue();
instance.Key=key;
});
}
function Xyz(key, value) {
return _extends(Abc).call(this, function (instance, _super) {
_super(key, value);
instance.That=function () {
alert('That');
};
});
}
Xyz
类:
function Abc(key, value) {
return _extends(Object).call(this, function (instance, _super) {
instance.What=function () {
alert('What');
};
instance.getValue=function () {
return 333+Number(value);
};
instance.Value=instance.getValue();
instance.Key=key;
});
}
function Xyz(key, value) {
return _extends(Abc).call(this, function (instance, _super) {
_super(key, value);
instance.That=function () {
alert('That');
};
});
}
示例代码:
var x=new Xyz('x', '123');
alert([x.Key, x.Value].join(': ')+'; isAbc: '+(x instanceof Abc));
var y=new Xyz('y', '456');
alert([y.Key, y.Value].join(': ')+'; isAbc: '+(y instanceof Abc));
var it=new Abc('it', '789');
alert([it.Key, it.Value].join(': ')+'; isAbc: '+(it instanceof Abc));
alert([it.Key, it.Value].join(': ')+'; isXyz: '+(it instanceof Xyz));
x.What();
y.That();
it.What();
it.That(); // will throw; it is not Xyz and does not have That method
我知道这并不能回答你的问题,因为据我所知,没有什么好方法可以将所有内容都放在函数构造函数中并让它使用原型 正如我所评论的,如果您在JavaScript语法方面有问题,那么这可能是一个不错的选择 下面是一个助手函数,我使用JavaScript(不带Object.create)继承和重写(调用super)
即使你找到了一种方法来编写帮助函数并使JS构造函数看起来像Java类,你也必须这样做。不。不。不。不。这不行。你在JavaScript中做继承完全错了。你的代码让我头疼 在JavaScript中创建伪经典继承模式 如果您需要类似于JavaScript中的类的东西,那么有很多库提供给您。例如,使用JavaScript,您可以按如下方式重新构造代码:
var augment = require("augment");
var ABC = augment(Object, function () {
this.constructor = function (key, value) {
this.key = key;
this.value = value;
};
this.what = function () {
alert("what");
};
});
var XYZ = augment(ABC, function (base) {
this.constructor = function (key, value) {
base.constructor.call(this, key, value);
};
this.that = function () {
alert("that");
};
});
var Abc = extend(Object, function () {
this.constructor = function (key, value) {
this.value = 333 + Number(value);
this.key = key;
};
this.what = function () {
alert("what");
};
});
var x = Xyz.new("x", "123");
var y = Xyz.new("y", "456");
var it = Abc.new("it", "789");
var it = Abc.new.apply(null, ["it", "789"]);
var ClassA = extend(Object, function () {
var ClassB = extend(this, function () {
// class definition
});
// rest of the class definition
alert(this.isPrototypeOf(ClassB)); // true
});
太好了!如果C++解决了你的问题,那就太好了。如果java不继续读下去,
原型类同构
在很多方面,原型与类相似。事实上,原型和类非常相似,我们可以使用原型来建模类。首先,让我们来看看:
上面的图片是从中拍摄的。我建议您仔细阅读。图表显示了我们:prototype
的属性,该属性指向构造函数的prototype对象constructor
的属性,该属性指向原型对象的构造函数原型继承的,而不是从构造函数继承的
原型
属性。但是,这些信息告诉我们,我们可以先创建原型对象,然后在其上定义构造函数
属性
例如,传统上我们可以写:
function ABC(key, value) {
this.key = key;
this.value = value;
}
ABC.prototype.what = function() {
alert("what");
};
然而,利用我们新发现的知识,我们可以写下如下内容:
var ABC = CLASS({
constructor: function (key, value) {
this.key = key;
this.value = value;
},
what: function () {
alert("what");
}
});
function CLASS(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
正如您所见,封装在JavaScript中很容易实现。您所需要做的就是从侧面思考。但是继承是另一个问题。您需要做更多的工作来实现继承
继承与超越
看看是如何增强的
:
请注意,最后三行与上一节中的CLASS
相同:
function CLASS(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
这告诉我们,一旦我们有了一个原型对象,我们需要做的就是获取它的构造函数属性并返回它
前三行增强用于:
对象创建派生类原型。创建
var it = Abc.new.apply(null, ["it", "789"]);
alert(x.key + ": " + x.value + "; isAbc: " + Abc.isPrototypeOf(x));
alert(y.key + ": " + y.value + "; isAbc: " + Abc.isPrototypeOf(y));
alert(it.key + ": " + it.value + "; isAbc: " + Abc.isPrototypeOf(it));
alert(it.key + ": " + it.value + "; isXyz: " + Xyz.isPrototypeOf(it));
alert(Abc.isPrototypeOf(Xyz)); // true
x.what();
y.that();
it.what();
it.that(); // will throw; it is not Xyz and does not have that method
var Xyz = extend(Abc, function (base) {
this.empty = this.new();
this.constructor = function (key, value) {
base.constructor.call(this, key, value);
};
this.that = function () {
alert("that");
};
});
var ClassA = extend(Object, function () {
var ClassB = extend(this, function () {
// class definition
});
// rest of the class definition
alert(this.isPrototypeOf(ClassB)); // true
});
var myClass = $.cls({
main: function() {
$('body').append('My App is loaded <br/>');
}
});
var mySecondClass = $.cls({
main: function() {
this._super();
$('body').append('My Second App is loaded <br/>');
}
}, myClass);
var app = new mySecondClass();
var Parent = function Parent () {
this.fname = 'Bob';
this.lname = 'Jones';
};
Parent.prototype.getFname = function getFname () {
return this.fname;
};
Parent.prototype.getLname = function getLname () {
return this.lname;
};
var Child = function Child () {
this.fname = 'Jim';
};
Child.prototype = Parent.prototype;
var child = new Child();
document.write(child.getFname()); //=> Jim