问题描述
我正在编写一个不需要的图像处理库,以期希望学习如何以正确且高效的方式使用javascript创建一个简单的库或框架。
基本流程图如下所示:
创建图像对象->指定URL和颜色模式->初始化对象,以便针对当前图像的颜色模式将主要操作方法设置为特定的方法->使用这些操作方法。
我对更多的经验丰富的编码人员将如何处理这种情况感到好奇。 因此,如果您认为有更好的方法或更有趣的方法,也请分享您的流程图,我很想学习。
这是我的代码段:
function ImageLib(URL,colormode){
this.url = URL;
this.ColorMode = colormode;
}
ImageLib.prototype.init = function() {
Switch (this.ColorMode ) {
case "BlackAndWhite" :
this.colorEnhance = ImageLib.ColorModeHandlers.BlackAndWhite.method1;
this.resize = ImageLib.ColorModeHandlers.BlackAndWhite.method2;
this.sharpen = ImageLib.ColorModeHandlers.BlackAndWhite.method3;
this.blur = ImageLib.ColorModeHandlers.BlackAndWhite.method4;
break;
case "SemiTransparent" :
this.colorEnhance = ImageLib.ColorModeHandlers.SemiTransparent.method1;
this.resize = ImageLib.ColorModeHandlers.SemiTransparent.method2;
this.sharpen = ImageLib.ColorModeHandlers.SemiTransparent.method3;
this.blur = ImageLib.ColorModeHandlers.SemiTransparent.method4;
break;
case "Sephia" :
this.colorEnhance = ImageLib.ColorModeHandlers.Sephia.method1;
this.resize = ImageLib.ColorModeHandlers.Sephia.method2;
this.sharpen = ImageLib.ColorModeHandlers.Sephia.method3;
this.blur = ImageLib.ColorModeHandlers.Sephia.method4;
break;
case "FullColor" :
case default:
this.colorEnhance = ImageLib.ColorModeHandlers.FullColor.method1;
this.resize = ImageLib.ColorModeHandlers.FullColor.method2;
this.sharpen = ImageLib.ColorModeHandlers.FullColor.method3;
this.blur = ImageLib.ColorModeHandlers.FullColor.method4;
break;
}
};
}
ImageLib.prototype.ColorModeHandlers.BlackAndWhite = {
method1: function (){...},
method2: function (){...},
method3: function (){...},
method4: function (){...}
}
ImageLib.prototype.ColorModeHandlers.SemiTransparent = {
method1: function (){...},
method2: function (){...},
method3: function (){...},
method4: function (){...}
}
ImageLib.prototype.ColorModeHandlers.Sephia = {
method1: function (){...},
method2: function (){...},
method3: function (){...},
method4: function (){...}
}
ImageLib.prototype.ColorModeHandlers.FullColor = {
method1: function (){...},
method2: function (){...},
method3: function (){...},
method4: function (){...}
}
image1 = new ImageLib("url","Sephia");
image1.init();
image1.sharpen();
image1.ColorEnhance();
etc...
首先,显然ImageLib.prototype.ColorModeHandlers.Sephia = {...}不起作用。 我找不到关于object.prototype.property.property嵌套的任何文章或问题。
我怎样才能做到这一点? 用子属性和方法声明嵌套属性的正确方法是什么?
而且由于找不到类似这样的嵌套属性的文章,这是不好的做法吗?
1楼
ImageLib.prototype.ColorModeHandlers.Sephia = {...}不起作用。
由于没有声明ColorModeHandlers,它将引发错误。 为此,我将使用如下所述的对象绑定表示法,通过这种方式,您将能够拥有嵌套属性。 您还可以使用其他符号来引用属性,以使您的代码更加清晰(例如,看起来像init方法)。
function ImageLib(URL,colormode){
this.url = URL;
this.ColorMode = colormode;
}
ImageLib.prototype.init = function() {
this.colorEnhance = this.ColorModeHandlers[this.ColorMode].method1;
this.resize = this.ColorModeHandlers[this.ColorMode].method2;
this.sharpen = this.ColorModeHandlers[this.ColorMode].method3;
this.blur = this.ColorModeHandlers[this.ColorMode].method4;
}
ImageLib.prototype.ColorModeHandlers = {
SemiTransparent : {
method1: function (){console.log("semiTransparent method 1")},
method2: function (){console.log("semiTransparent method 2")},
method3: function (){console.log("semiTransparent method 3")},
method4: function (){console.log("semiTransparent method 4")}
}, BlackAndWhite : {
method1: function (){console.log("BlackAndWhite method 1")},
method2: function (){console.log("BlackAndWhite method 2")},
method3: function (){console.log("BlackAndWhite method 3")},
method4: function (){console.log("BlackAndWhite method 4")}
}
}
image1 = new ImageLib("url","Sephia");
image1.init();
image1.sharpen();
image1.ColorEnhance();
2楼
它不起作用的原因很简单。 当您尝试定义嵌套属性时,该属性不存在。 因此无法访问嵌套。 因此声明应该如下所示:
ImageLib.prototype.ColorModeHandlers = {
BlackAndWhite: {
method1: function () {...},
method2: function () {...},
method3: function () {...},
method4: function () {...}
},
SemiTransparent: {
method1: function () {...},
method2: function () {...},
method3: function () {...},
method4: function () {...}
}
...
}
但是,您现在应该对这种方法有两点看法。
当您将其包装在嵌套级别中时,这些方法将无法直接使用。 即
var image1 = new ImageLib(“ url”); image1.ColorModeHandlers.FullColor.method2(); 因为
method2
内的this
(很可能将在所有这些方法中使用)将引用FullColor
对象。 因此,您需要按照示例代码init
函数中的方式对其进行分配,并且仅在通过image.resize()
使用该函数之后才进行image.resize()
。您将无法在所有
methodN
函数(即闭包)中使用私有状态,因为只有它们的一个实例(因为存储在原型中),并且此状态将在ImageLib
所有实例之间共享。 避免这种情况的模式称为寄生继承 。 对于javascript初学者来说,这是一个相当复杂的概念。 但是,如果您需要私有状态,则可以此处了解
关于这是否是一个好习惯,答案是非常有根据的。
就我个人而言,我希望保留一堆不拆分为子对象的方法,并将传递mode
作为参数。
否则,这些方法将仅针对具有此模式作为属性的对象( ImageLib
实例)启动,因此可以通过this.mode
访问
3楼
首先,回答一个简单的问题:
ImageLib.prototype.ColorModeHandlers.Sephia = {...};
那是行不通的,因为您没有在任何地方初始化ImageLib.prototype.ColorModeHandlers
。
如果先执行以下操作,则这些分配应该起作用:
ImageLib.prototype.ColorModeHandlers = {};
但是为什么这些处理程序对象应该在原型上?
似乎没有任何理由将它们放在那里。
实际上,您在init()
中的代码根本不使用ImageLib.prototype.ColorModeHandlers
;
它使用ImageLib.ColorModeHandlers
这对我来说更有意义。
所以我改为这样做:
ImageLib.ColorModeHandlers = {};
ImageLib.ColorModeHandlers.BlackAndWhite = {...};
甚至更好:
ImageLib.ColorModeHandlers = {
BlackAndWhite: {...},
SemiTransparent: {...},
...
};
接下来,不要使用无意义的名称,例如method1
, method2
等。这些名称是否不应该与代码中其他地方使用的有意义的名称相同,例如method1
应该命名为colorEnhance
?
最重要的一点:永远不要重复代码!
每当您发现自己复制并粘贴代码块时,请自己想一想:“没有一种方法可以组合这些代码块吗?”
如果您按照我上面的建议使用匹配名称( colorEnhance
而不是method1
等),那么您的init
函数可以简单地是:
ImageLib.prototype.init = function() {
var handlers =
ImageLib.ColorModeHandlers[this.ColorMode] ||
ImageLib.ColorModeHandlers.FullColor;
for( var name in handlers ) {
this[name] = handlers[name];
}
};
现在,我们消除了所有重复。
而且,如果以后要添加另一种处理程序,则不必更新switch语句中的所有用例,只需将新的处理程序添加到每个ColorModeHandlers
对象中,它就可以正常工作。