面向对象的JavaScript:私有/公共模式

时间:2014-02-21 07:43:25

标签: javascript object-oriented-analysis

全部 -

正如道格拉斯·克罗克福德(Douglas Crockford)所描述的那样,在Javascript中实现信息隐藏的经典模式:

http://javascript.crockford.com/private.html

我也知道我在这里展示的另一个: http://jsfiddle.net/TvsW6/4/

并总结如下:

function LogSystem(anotherPrivateVar) {
//. . 

  var _setting1;
  this.setting2;

  function _printLog(msg) {
    $("#" + _divId).append(msg + "<br/>");
  };

  return {
    printLog :function(msg) {
      console.log("PRINTING:" + msg);
      _printLog(msg);
    },
    logSetting_pub: function() {
       this.printLog("PUB: Setting1 is: " + _setting1);
       this.printLog("PUB: Setting2 is: " + this.setting2);
    }
//..
  };
};

问题

除了这两个模式之外还有其他模式在JavaScript中实现公共和私有方法和成员吗?这两种模式有名字吗?你是否喜欢这两个(或更多!)

非常感谢你的帮助。我发现在原始JavaScript中了解高级主题是很少见的技巧,我想拥有它们!

3 个答案:

答案 0 :(得分:1)

Crockford的方法可能是我遇到的最多的方法。坦率地说,它让我很伤心,因为它很乱,语义太糟糕 - 你的构造函数代码与你的类定​​义混合在一起! - ,如果我记得以前的测试,效率低下。

我认为我从未见过你在野外描述的第二种风格。由于类似的原因,它也不会让我感到很舒服。更不用说从构造函数返回是一个相当模糊的行为,这可能会使许多人感到困惑。

我赞成的风格是“契约”私人之一,或者更确切地说,有利于“受保护”的成员。我自己can be found here的一个相当不错的例子。

代码的相关子集是:

var gk = (function(gk){

//static/constant members would be vars here, if I had them.

function List(collection){
    this._dummy = {};
    this._dummy.next = this._dummy;
    this._dummy.prev = this._dummy;
    this.length = 0;

    if(collection){
        this.addAll(collection);
    }
}

List.prototype = new gk.Collection();

//stuff...

List.prototype.pushBack = function(item){
    var curNode = this._dummy;
    var newNode = {};
    newNode.item = item;
    this._add(curNode, newNode);
}

List.prototype.add = List.prototype.pushBack;

List.prototype._add = function(curNode, newNode){
    newNode.prev = curNode.prev;
    curNode.prev.next = newNode;
    newNode.next = curNode;
    curNode.prev = newNode;
    ++this.length;
    this._registerAddition(curNode.item); //inherited from the superclass!
}

//stuff...

gk.List = List;

return gk;
})(gk || {}); 

所有公共和“私人”成员都附加到this或原型,但任何旨在“特定于实现”的内容都以下划线为前缀。这表明它不是一个公开保证的API,并且引用它会立即将您与实现紧密结合。如果你打算有一个可公开访问的对象可以将其内部暴露给需要它们的东西(例如我的LinkedList,它可能需要更多控制,但仍然是一个完全有效的数据结构的内部使用,这很好。独自)。

作为一个额外的好处,生成的代码(在我看来)是干净的,可维护的,语义的,并且无论“安全性”如何,都可以统一访问成员。从公共/私有状态重构某些内容也更容易,因为您只需添加/删除下划线。您还可以获得原型链的全部好处(抽象受保护的成员供超级类使用!)。因此,如果你关心那种事情,那么每个实例的开销似乎有点一点(手头没有测试,对不起)。

我很久以前就放弃了尝试将JS变成Java / C ++ / C#的完美克隆。这是一种不同的语言。在我看来,你可能只是让自己更容易开发,并制作干净,可读,可维护和可用的代码,而不是创建令人沮丧的怪物,这些怪物基于闭包的荣耀来模仿其他语言。是的,你可以做任何关闭的事情,但亲爱的上帝,这并不意味着你应该。

答案 1 :(得分:0)

anotherPrivateVar不是私人会员。它是函数的参数。在这种情况下,构造函数的参数。 _setting1无法另行声明。

我认为您的最后两个公共函数printLoglogSetting_pub不是定义公共函数的最佳方法。请改用原型:

LogSystem.prototype.printLog = function(msg) {...}

编辑:您可能也对coffeescript感兴趣。它有一个更好的方法来开发面向对象,类,构造函数等。但主要是它的另一种语法的javascript。

答案 2 :(得分:0)

我最喜欢的模式是Mozilla网站上的described

Object.defineProperty(obj, "value", {
  enumerable: true,
  configurable: false,
  writable: true,
  value: 5
});

此外,您可以为此类属性添加getter和setter。