当前位置: 代码迷 >> JavaScript >> 用原型创建嵌套属性是一种好习惯吗? 以及如何正确地做呢?
  详细解决方案

用原型创建嵌套属性是一种好习惯吗? 以及如何正确地做呢?

热度:74   发布时间:2023-06-13 12:13:14.0

我正在编写一个不需要的图像处理库,以期希望学习如何以正确且高效的方式使用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嵌套的任何文章或问题。

我怎样才能做到这一点? 用子属性和方法声明嵌套属性的正确方法是什么?

而且由于找不到类似这样的嵌套属性的文章,这是不好的做法吗?

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();

它不起作用的原因很简单。 当您尝试定义嵌套属性时,该属性不存在。 因此无法访问嵌套。 因此声明应该如下所示:

ImageLib.prototype.ColorModeHandlers = {
    BlackAndWhite: {
        method1: function () {...},
        method2: function () {...},
        method3: function () {...},
        method4: function () {...}
    },
    SemiTransparent: {
        method1: function () {...},
        method2: function () {...},
        method3: function () {...},
        method4: function () {...}
    }
 ...
}

但是,您现在应该对这种方法有两点看法。

  1. 当您将其包装在嵌套级别中时,这些方法将无法直接使用。

    var image1 = new ImageLib(“ url”); image1.ColorModeHandlers.FullColor.method2(); 因为method2内的this (很可能将在所有这些方法中使用)将引用FullColor对象。 因此,您需要按照示例代码init函数中的方式对其进行分配,并且仅在通过image.resize()使用该函数之后才进行image.resize()

  2. 您将无法在所有methodN函数(即闭包)中使用私有状态,因为只有它们的一个实例(因为存储在原型中),并且此状态将在ImageLib所有实例之间共享。 避免这种情况的模式称为寄生继承 对于javascript初学者来说,这是一个相当复杂的概念。 但是,如果您需要私有状态,则可以此处了解

关于这是否是一个好习惯,答案是非常有根据的。 就我个人而言,我希望保留一堆不拆分为子对象的方法,并将传递mode作为参数。 否则,这些方法将仅针对具有此模式作为属性的对象( ImageLib实例)启动,因此可以通过this.mode访问

首先,回答一个简单的问题:

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: {...},
    ...
};

接下来,不要使用无意义的名称,例如method1method2等。这些名称是否不应该与代码中其他地方使用的有意义的名称相同,例如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对象中,它就可以正常工作。

  相关解决方案