用Javascript扩展原型——好方法?
我想验证我在扩展原型时使用的方法是正确的——假设“extend”是正确的词 这个主题有很多克隆。我仍在努力正确理解这个话题 目的是: -写干净好的代码。 -为了避免使用框架,如果可能,使用纯Javascript。 -获取关于干净框架的建议,这些框架不会扭曲JS以获得支持类的行为 以下是我的沙盒的父原型:用Javascript扩展原型——好方法?,javascript,oop,inheritance,prototype,extend,Javascript,Oop,Inheritance,Prototype,Extend,我想验证我在扩展原型时使用的方法是正确的——假设“extend”是正确的词 这个主题有很多克隆。我仍在努力正确理解这个话题 目的是: -写干净好的代码。 -为了避免使用框架,如果可能,使用纯Javascript。 -获取关于干净框架的建议,这些框架不会扭曲JS以获得支持类的行为 以下是我的沙盒的父原型: function Parent(){ } Parent.prototype = { "init":function(){ this.name = "anon";
function Parent(){
}
Parent.prototype = {
"init":function(){
this.name = "anon";
},
"initWithParameters":function(parameters){
this.name = parameters.name ? parameters.name : "anon";
},
"talk": function(){
console.log('Parent is: ' + this.name);
}
}
现在,子原型-它添加了一个“位置”属性并重新定义了行为:
function Child(){
Parent.call(this);
}
Child.prototype = new Parent;
Child.prototype.constructor = Child;
Child.prototype.init = function(){
Parent.prototype.call(this);
this.setPosition(0, 0);
}
Child.prototype.initWithParameters = function(parameters){
Parent.prototype.initWithParameters.call(this, parameters);
if(!this.position){
this.position = {x:0, y:0};
}
this.setPosition(parameters.pos.x, parameters.pos.y);
}
Child.prototype.setPosition = function(x, y){
this.position.x = x;
this.position.y = y;
}
Child.prototype.talk = function(){
console.log('Child is: ' + this.name + ' and location is: ' + this.position.x + ', ' + this.position.y);
}
这是一种好的做法吗?在重写属性时,是否没有避免写“Child.prototype.”的速记方法(可能使用literal,就像编写父原型一样)
我知道J.Resig的类/扩展方法。但我宁愿使用Javascript作为它的原型语言,而不是让它作为一种“类行为的无类OO语言”工作
感谢您的帮助:-)您的方法这是一种很好的纯JavaScript方法。每次给“Child.prototype”小费的唯一办法就是把它放在一个参考变量中 比如: 但你仍然在做这个背后的儿童原型。您还可以定义一个函数来完成此操作,请参见下划线绑定,也许它适合您的需要
干杯对于这个建议,我可能会非常激动,因为在我的示例中,有几篇文章可能会反对某些做法,但这对我来说很有效,对于外观整洁的代码来说效果很好,保持一致性,缩小规模,在严格模式下运行,并且与IE8兼容 我还喜欢使用原型方法(而不是你随处可见的所有“扩展”或“应用”样式) 我这样写我的课。是的,它看起来很像你不想要的OOP语言,但它仍然遵循原型模型,同时与其他熟悉的语言有相似之处,这使得项目更容易导航 这是我喜欢的风格:)我不是说这是最好的,但它很容易阅读
(function(ns) {
var Class = ns.ClassName = function() {
};
Class.prototype = new baseClass();
Class.constructor = Class;
var _public = Class.prototype;
var _private = _public._ = {};
Class.aClassProperty = "aValue";
Class.aClassMethod = function(params) {
}
_public.aMethod = function(params) {
_private.myMethod.call(this, "aParam");
Class.aClassMethod("aParam");
}
_private.myMethod = function(params) {
}
})({});
编辑:
我继续将您的示例转换为这种样式,只是为了向您展示它的外观:
var namespace = {};
(function(ns) {
var Class = ns.Parent = function() {
};
var _public = Class.prototype;
var _private = _public._ = {};
_public.init = function() {
this.name = "anon";
}
_public.initWithParameters = function(parameters) {
this.name = parameters.name ? parameters.name : "anon";
}
_public.talk = function() {
console.log('Parent is: ' + this.name);
}
})(namespace);
(function(ns) {
var Class = ns.Child = function() {
this.position = {x:0, y:0};
};
Class.prototype = new ns.Parent();
Class.constructor = Class;
var _public = Class.prototype;
var _private = _public._ = {};
_public.init = function() {
_public.init.call(this);
this.setPosition(0, 0);
}
_public.initWithParameters = function(parameters) {
_public.initWithParameters.call(this, parameters);
this.setPosition(parameters.pos.x, parameters.pos.y);
}
_public.setPosition = function(x, y) {
this.position.x = x;
this.position.y = y;
}
_public.talk = function() {
console.log('Child is: ' + this.name + ' and location is: ' + this.position.x + ', ' + this.position.y);
}
})(namespace);
一般来说,您的方法可行,但更好的方法是替换:
Child.prototype = new Parent;
与:
这样,您就不需要调用新父级
,这在某种程度上是一种反模式。您还可以按如下方式直接定义新特性:
Child.prototype = Object.create(Parent.prototype, {
setPosition: {
value: function() {
//... etc
},
writable: true,
enumerable: true,
configurable: true
}
});
希望这有帮助
以下是我通常的做法: 使用辅助函数:
/**
* A clone of the Node.js util.inherits() function. This will require
* browser support for the ES5 Object.create() method.
*
* @param {Function} ctor
* The child constructor.
* @param {Function} superCtor
* The parent constructor.
*/
function inherits (ctor, superCtor) {
ctor.super_ = superCtor;
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false
}
});
};
然后你可以简单地做:
function ChildClass() {
inherits(this, ParentClass);
// If you want to call parent's constructor:
this.super_.apply(this, arguments);
}
使用Lodash扩展原型
_.assign(ChildClass.prototype, {
value: key
});
或者给ES6一个机会强>
class ParentClass {
constructor() {
var date = new Date();
var hours = date.getHours();
var minutes = date.getMinutes();
var seconds = date.getSeconds();
this.initializeTime = hours + ':' + minutes + ':' + seconds;
}
}
class ChildClass extends ParentsClass {
constructor() {
super();
console.log(this.initializeTime);
}
}
2019年来自谷歌 从中可以看出,扩展原型的方法是:
函数MyClass(){
调用(this);
}
//继承一个类
MyClass.prototype=Object.create(SuperClass.prototype);
//混入另一个
Object.assign(MyClass.prototype{
//…你拥有自己的原型。。。
});
//重新分配构造函数
MyClass.prototype.constructor=MyClass代码>我的示例演示了几件事:私有变量、parant和子构造函数的相同解析参数、rewrite.toString()函数try:“”+this
:)
文档的完整示例:
输出:
构造函数参数
扩展子类中的函数
增量变量
私有变量
保护变量
/**
*父类的类接口
*
*@级
*/
函数父函数(){
this.parseArguments(…参数);
/**
*隐藏变量
*
*@type{Boolean}
*@私人
*/
var hidden=true;
/**
*躲起来
*/
this.getHidden=()=>{
log(this+“:hidden(private var)is”,hidden);
}
/**
*隐藏
*
*@param{Boolean}状态隐藏的新值
*/
this.setHidden=(状态)=>{
log(此+”:隐藏(私有变量)设置为“,!!状态);
隐藏=状态;
}
defineProperty(这个,“_id”,{value:“312”});
}
Object.defineProperty(Parent.prototype,“nameString”,{value:“Parent”});
/**
*解析参数
*/
Parent.prototype.parseArguments=函数(arg1,arg2){
this.arg1=arg1;
this.arg2=arg2;
};
/**
*使用`class.toString()获取类名`
*/
Parent.prototype.toString=函数(){
返回此.nameString;
};
/**
*初始化中间件
*/
Parent.prototype.init=函数(){
log(this+“:默认输出”);
};
/**
*增值
*/
Parent.prototype.increment=函数(){
this.value=(this.value)?this.value+1:1;
console.log(this+“:increment”,this.value);
};
/**
*子类的类接口
*
*@级
*/
函数childInterface(){
this.parseArguments(…参数);
}
//延伸
childInterface.prototype=新父级();
Object.defineProperty(childInterface.prototype,“nameString”,{value:“childInterface”});
/**
*初始化中间件(重写默认值)
*/
childInterface.prototype.init=函数(chatClient){
log(this+“:新输出”);
};
/**
*Child2的类接口
*
*@级
*/
函数child2Interface(){
this.parseArguments(…参数);
}
//延伸
child2Interface.prototype=new Parent();
Object.defineProperty(child2Interface.prototype,“nameString”,{value:“child2Interface”});
//---------------------------------------------------------
//---------------------------------------------------------
MM=新的父项(“arg1的值”、“arg2的值”);
Child1=新的childInterface(“1”、“2”);
Child2=新的Child2接口(“a”、“b”);
日志(MM+“args:”,MM.arg1,MM.arg2);
log(Child1+“args:”,Child1.arg1,Child1.arg2);
日志(Child2+“args:”,Child2.arg1,Child2.arg2);
控制台日志(“”);
MM.init();
Child1.init();
Child2.init();
控制台日志(“”);
MM.增量();
Child1.increment();
Child2.increment();
Child2.increment();
MM.增量();
控制台日志(“p”、“c1”、“c2”);
console.log(MM.value,“+Child1.v
_.assign(ChildClass.prototype, {
value: key
});
class ParentClass {
constructor() {
var date = new Date();
var hours = date.getHours();
var minutes = date.getMinutes();
var seconds = date.getSeconds();
this.initializeTime = hours + ':' + minutes + ':' + seconds;
}
}
class ChildClass extends ParentsClass {
constructor() {
super();
console.log(this.initializeTime);
}
}
MM = new Parent("val of arg1", "val of arg2");
Child1 = new childInterface("1", "2");
Child2 = new child2Interface("a", "b");
console.log(MM + "args:", MM.arg1, MM.arg2);
// Parentargs: val of arg1 val of arg2
console.log(Child1 + "args:", Child1.arg1, Child1.arg2);
// childInterfaceargs: 1 2
console.log(Child2 + "args:", Child2.arg1, Child2.arg2);
// child2Interfaceargs: a b
MM.init();
// Parent: default ouput
Child1.init();
// childInterface: new output
Child2.init();
// child2Interface: default ouput
MM.increment();
// Parent: increment 1
Child1.increment();
// childInterface: increment 1
Child2.increment();
// child2Interface: increment 1
Child2.increment();
// child2Interface: increment 2
MM.increment();
// Parent: increment 2
console.log("p", "c1", "c2");
// p c1 c2
console.log(MM.value, " " + Child1.value, " " + Child2.value);
// 2 1 2
MM.getHidden();
// Parent: hidden (private var) is true
MM.setHidden(false);
// Parent: hidden (private var) set to false
Child2.getHidden();
// child2Interface: hidden (private var) is true
MM.setHidden(true);
// Parent: hidden (private var) set to true
Child2.setHidden(false);
// child2Interface: hidden (private var) set to false
MM.getHidden();
// Parent: hidden (private var) is true
Child1.getHidden();
// childInterface: hidden (private var) is true
Child2.getHidden();
// child2Interface: hidden (private var) is false
function Parent() {
//...
Object.defineProperty(this, "_id", { value: 312 });
};
console.log(MM._id); // 312
MM._id = "lol";
console.log(MM._id); // 312