1

我开始在一个相当大的 JS 项目上进行一些工作,并希望确保我干净有效地构建代码。我一直在阅读大量关于 JS 中 OOP 的不同方法,但还没有找到我真正喜欢的方法。

我很欣赏使用该prototype属性提供的性能改进,但是当您尝试将真正的私有方法和变量添加到混合中时,它会变得相当混乱。另一方面,我真的很喜欢这种closure方法,但我对性能下降感到不舒服。我查看了该module模式,但发现它非常冗长。某处有快乐的媒介吗?

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

积分等级:

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 = <value>. 同样,我可能会Point.getXY()在大部分时间调用,这将为本质上是公共属性的内容构建新对象。我应该摆脱Point类的 getter 和 setter 的概念,让它创建完全开放的公共对象吗?这在 OOP 的上下文中似乎是错误的。

对于User该类,我想在内部存储一个 GUID,以便可以请求但从不修改它。这不能用这种prototype方法来完成(除非我遗漏了什么),所以我被迫使用某种closure. 我预计有数百名用户同时处于活动状态,因此性能并不像在Point课堂上那么重要。但是,我真的不想在整个代码库中切换不同类型的 OOP 样式。

所以,作为一个普遍的问题,在 JS 中是否有一种我缺少的 OOP 方法可以让我prototype在干净地将选择函数和变量私有化的同时使用该属性?或者,我看错了方向?我应该以不同的方式处理这个问题吗?

4

4 回答 4

1

您只能使用文档和约定(如_前缀)将方法标记为“内部”,但 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;
}
于 2012-07-01T21:17:39.507 回答
0

我不知道你的背景,但可能是的,所以看看咖啡脚本

于 2012-07-01T17:17:32.193 回答
0

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

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

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

如果你真的需要私有函数,我鼓励你处理你必须在闭包模式中处理的混乱。

于 2012-07-01T17:35:02.660 回答
0

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

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;
            }
        }
    }
}
于 2012-07-01T20:59:02.593 回答