这两个小JavaScript类的最佳OOP方法

这两个小JavaScript类的最佳OOP方法,javascript,oop,design-patterns,Javascript,Oop,Design Patterns,我正在着手一个相当大的JS项目,并希望确保我的代码结构清晰高效。我一直在阅读JS中大量不同的OOP方法,但还没有找到一种我真正喜欢的方法 我很欣赏使用prototype属性所带来的性能改进,但是当您试图在混合中添加真正的私有方法和变量时,它会变得相当混乱。另一方面,我非常喜欢闭包方法,但我对性能下降感到不舒服。我查看了模块模式,但发现它非常冗长。有快乐的媒介吗 为了说明我正在努力解决的问题,这里有两个非常小的示例类: 点类: function Point(x, y) { this.x = x

我正在着手一个相当大的JS项目,并希望确保我的代码结构清晰高效。我一直在阅读JS中大量不同的OOP方法,但还没有找到一种我真正喜欢的方法

我很欣赏使用
prototype
属性所带来的性能改进,但是当您试图在混合中添加真正的私有方法和变量时,它会变得相当混乱。另一方面,我非常喜欢
闭包
方法,但我对性能下降感到不舒服。我查看了
模块
模式,但发现它非常冗长。有快乐的媒介吗

为了说明我正在努力解决的问题,这里有两个非常小的示例类:

点类:

function Point(x, y) {
  this.x = x;
  this.y = y;
}

// Get the x coordinate.
Point.prototype.getX = function() {
  return this.x;
}

// Get the y coordinate.
Point.prototype.getY = function() {
  return this.y;
}

// Get the (x, y) coordinate.
Point.prototype.getXY = function() {
  return {x: this.x, y: this.y};
}

// Set the x coordinate.
Point.prototype.setX = function(x) {
  this.x = x;
}

// Set the y coordinate.
Point.prototype.setY = function(y) {
  this.y = y;
}

// Set the (x, y) coordinate.
Point.prototype.setXY = function(x, y) {
  this.x = x;
  this.y = y;
}
function User(guid) {
  var guid = guid;

  // Return the user's GUID.
  this.getGuid = function() {
    return guid;    
  }
}
用户类:

function Point(x, y) {
  this.x = x;
  this.y = y;
}

// Get the x coordinate.
Point.prototype.getX = function() {
  return this.x;
}

// Get the y coordinate.
Point.prototype.getY = function() {
  return this.y;
}

// Get the (x, y) coordinate.
Point.prototype.getXY = function() {
  return {x: this.x, y: this.y};
}

// Set the x coordinate.
Point.prototype.setX = function(x) {
  this.x = x;
}

// Set the y coordinate.
Point.prototype.setY = function(y) {
  this.y = y;
}

// Set the (x, y) coordinate.
Point.prototype.setXY = function(x, y) {
  this.x = x;
  this.y = y;
}
function User(guid) {
  var guid = guid;

  // Return the user's GUID.
  this.getGuid = function() {
    return guid;    
  }
}
在任何一个给定的时间都可能有数千个点对象在使用,因此我觉得
prototype
方法是最好的选择。但是,如果我想在坐标设置中添加任何验证,只需调用
Point.x=
即可绕过。类似地,我可能会在大部分时间调用
Point.getXY()
,这将为本质上属于公共属性的对象构造新对象。我是否应该摆脱
Point
类的getter和setter概念,让它创建完全开放的公共对象?在面向对象的上下文中,这似乎是错误的

对于
User
类,我希望在内部存储一个GUID,这样就可以请求它,但永远不会修改它。这不能用
prototype
方法来完成(除非我遗漏了什么),所以我不得不使用某种
闭包。我预计一次激活的用户数量将达到数百,因此性能不如
Point
类重要。然而,我并不想在整个代码库中切换不同类型的OOP风格


因此,作为一个一般性的问题,在JS中是否有一种我缺少的OOP方法,它允许我在干净地私有化选择函数和变量的同时使用
prototype
属性?或者,我看错方向了吗?我应该换一种方式来处理这个问题吗?

我不知道你的背景,但可能是面向对象的,所以请检查一下

我不知道你的背景,但可能是面向对象的,所以请检查一下

因为基于原型的对象定向不是真正的对象定向,我认为你可能找错了地方

基于原型的对象是它们的子类的克隆。因此,如果您声明对象有一个属性getXY(),那么它对从该属性克隆的任何对象都是开放的

所以我想真正的问题是,在这个实现中,您认为私有函数能为您带来什么


如果您真的需要私有函数,我建议您处理闭包模式中必须处理的混乱

由于基于原型的面向对象不是真正的面向对象,我认为您可能找错了地方

基于原型的对象是它们的子类的克隆。因此,如果您声明对象有一个属性getXY(),那么它对从该属性克隆的任何对象都是开放的

所以我想真正的问题是,在这个实现中,您认为私有函数能为您带来什么


如果您真的需要私有函数,我建议您处理闭包模式中必须处理的混乱

您可以在开发过程中使用闭包方法,这样您就知道没有人会绕过验证,然后在发布代码时切换到更快的原型方法

var Release = true;
if (Release) {
    function Point(x, y) {
        this.x = x;
        this.y = y;
    }

    // Get the x coordinate.
    Point.prototype.getX = function () {
        return this.x;
    }

    // Get the y coordinate.
    Point.prototype.getY = function () {
        return this.y;
    }

    // Get the (x, y) coordinate.
    Point.prototype.getXY = function () {
        return {
            x: this.x,
            y: this.y
        };
    }

    // Set the x coordinate.
    Point.prototype.setX = function (x) {
        this.x = x;
    }

    // Set the y coordinate.
    Point.prototype.setY = function (y) {
        this.y = y;
    }

    // Set the (x, y) coordinate.
    Point.prototype.setXY = function (x, y) {
        this.x = x;
        this.y = y;
    }
} else {
    function Point(x, y) {
        var _x = x,
            _y = y;
        return {
            // Get the x coordinate.
            getX: function () {
                return _x;
            },

            // Get the y coordinate.
            getY: function () {
                return _y;
            },

            // Get the (x, y) coordinate.
            getXY: function () {
                return {
                    x: _x,
                    y: _y
                };
            },

            // Set the x coordinate.
            setX: function (x) {
                _x = x;
            },

            // Set the y coordinate.
            setY: function (y) {
                _y = y;
            },

            // Set the (x, y) coordinate.
            setXY: function (x, y) {
                _x = x;
                _y = y;
            }
        }
    }
}

您可以在开发过程中使用闭包方法,这样您就知道没有人会绕过验证,然后在发布代码时切换到更快的原型方法

var Release = true;
if (Release) {
    function Point(x, y) {
        this.x = x;
        this.y = y;
    }

    // Get the x coordinate.
    Point.prototype.getX = function () {
        return this.x;
    }

    // Get the y coordinate.
    Point.prototype.getY = function () {
        return this.y;
    }

    // Get the (x, y) coordinate.
    Point.prototype.getXY = function () {
        return {
            x: this.x,
            y: this.y
        };
    }

    // Set the x coordinate.
    Point.prototype.setX = function (x) {
        this.x = x;
    }

    // Set the y coordinate.
    Point.prototype.setY = function (y) {
        this.y = y;
    }

    // Set the (x, y) coordinate.
    Point.prototype.setXY = function (x, y) {
        this.x = x;
        this.y = y;
    }
} else {
    function Point(x, y) {
        var _x = x,
            _y = y;
        return {
            // Get the x coordinate.
            getX: function () {
                return _x;
            },

            // Get the y coordinate.
            getY: function () {
                return _y;
            },

            // Get the (x, y) coordinate.
            getXY: function () {
                return {
                    x: _x,
                    y: _y
                };
            },

            // Set the x coordinate.
            setX: function (x) {
                _x = x;
            },

            // Set the y coordinate.
            setY: function (y) {
                _y = y;
            },

            // Set the (x, y) coordinate.
            setXY: function (x, y) {
                _x = x;
                _y = y;
            }
        }
    }
}

您只能使用文档和约定(如
\uuu
前缀)将方法标记为“内部”,但javascript中没有真正的、强制的对象私有成员

闭包是不可接受的——它们将拥有数据,而不是可能具有“有趣”结果的对象,特别是当您希望以这种方式使用闭包扩展“类”时。 另一点是,您将使用O(n)内存来存储所有函数对象,这是不可接受的,如果该库的用户无法控制它,他们可能很容易使用该库,从而导致内存问题

您可以使用下划线前缀约定,如下所示:

function Point(x, y) {
  this._x = x;
  this._y = y;
}

// Get the x coordinate.
Point.prototype.getX = function() {
  return this._x;
}

// Get the y coordinate.
Point.prototype.getY = function() {
  return this._y;
}

您只能使用文档和约定(如
\uuu
前缀)将方法标记为“内部”,但javascript中没有真正的、强制的对象私有成员

闭包是不可接受的——它们将拥有数据,而不是可能具有“有趣”结果的对象,特别是当您希望以这种方式使用闭包扩展“类”时。 另一点是,您将使用O(n)内存来存储所有函数对象,这是不可接受的,如果该库的用户无法控制它,他们可能很容易使用该库,从而导致内存问题

您可以使用下划线前缀约定,如下所示:

function Point(x, y) {
  this._x = x;
  this._y = y;
}

// Get the x coordinate.
Point.prototype.getX = function() {
  return this._x;
}

// Get the y coordinate.
Point.prototype.getY = function() {
  return this._y;
}

如果您真的想要隐私,请使用Dart或GWT。你真的想要它吗?@Esailija我认为隐私在整个代码库中都很重要,所以我想做相应的计划。然而,我觉得Dart和GWT作为这个问题的解决方案有点过头了。你只能使用像
\uu
前缀这样的约定来将一个方法标记为“内部”,但javascript中没有真正的隐私。闭包一点也不像它,只要你提出一个新的观点,你就会重新创建每个函数对象。如果有50个方法,你创建了1000个点,那么就创建了49950个额外的函数对象。最重要的是关闭