【问题标题】:how to have Javascript Object creation pattern with Reusable methods and private properties?如何使用可重用方法和私有属性创建 Javascript 对象模式?
【发布时间】:2012-09-28 18:31:45
【问题描述】:

考虑到具有私有属性的对象创建模式,一种方法是:

function MyStack (){
    var list = [],
        index = 0;

    this.push =  function(val){ 
        return list[index++] = val;
    };
    this.pop = function(){// ...}
}

var stack1 = new MyStack();       stack1.push(5);
var stack2 = new MyStack();       stack2.push(11);

这个问题:Stack 的每个实例都有自己的方法“push”和“pop”的副本。

实现构造方法的另一种方式是:

function MyStack(){ 
    this.list = []; 
    this.index = 0;
}
MyStack.prototype = {
    insert: function(val){
            return this.list[this.index++] = val;
        },
    pop:function(){//...}
}

这里的问题:我们失去了列表和索引的隐私。

有没有办法让我们可以在实例之间重用方法和属性的隐私?

我知道我们可以将这个用于不对对象的任何状态进行操作的方法,但我更多地谈论的是那些对状态进行操作的方法。

【问题讨论】:

  • 您可以给每个实例一个随机 ID,并将其私有属性存储在某种数据结构中。但如果你使用构造函数,我建议你忘记私有属性。 JavaScript 不是为此而构建的,任何解决方法都有一些缺点。
  • @FelixKling 假设我们有一个辅助 DS,例如 {id1: { list:[3,4],currentIndex:2}, id2: { list:[2,1,4], currentIndex:3} } ... 即使在 MyStack.prototype.insert = function(val){ currState = this.auxiliaryDS[this.id]; this.currState.list.push(val).. 同样,它并不是真正的私有。
  • 您可以在函数内部定义数据存储和构造函数,并且只公开构造函数。然后,数据存储将是私有的,无法从外部访问。是的,该 ID 可以访问,但如果您想对其进行混淆,您甚至可以为此生成一个随机属性名称。正如我所说的,JS 不是为此而构建的,你所做的任何事情都会变得笨拙和/或复杂。适当的文件是更有价值的国际海事组织。你可以在这里找到很多相关的问题:stackoverflow.com/…
  • @FelixKling 谢谢。我明白你的意思,尽管考虑到 JS 的灵活性,当你说“JS 不是为此而构建的”时,我不得不说这是一个很大的声明。 !
  • 这里没有太多的答案。但是,在不至于荒谬的情况下,您可以将可公开访问的方法包装在原型中......或者,您可以将一组单一的辅助函数包装在第二个外部闭包中,该外部闭包包装您的预期构造函数(“静态”,私有函数)。从那里您可以公开一个命令类型的接口,该接口处理运行内部功能,以及在需要时使用私钥/索引注册单个实例。你永远不会使用 Prototype,但你会通过共享助手来节省内存,但会花费更多的时钟。

标签: javascript jquery oop design-patterns object


【解决方案1】:

是的。我已经编辑了这段代码,所以它实际上完全可以按照您的预期工作。这对我来说似乎有点多余,但是,它确实为您提供了提供公共接口的能力,但可以让您的变量保持私有并控制用户与它们交互的方式。

function MyStack(){ 
    var list = []; 
    var index = 0;

    this.getIndex = function(){
        return index;
    }
    this.setIndex = function(val){
        index = val;
    }
    this.list = function(val){
        if(val){
           // setter if a value was provided. Illustrating how you can control
           // index, which I assume is the point of having these things private 
           // to begin with
           return list[this.setIndex(this.getIndex() + 1)] = val;
        }

        // always return list - acts like a getter
        return list;
    }
}
MyStack.prototype = {
    insert: function(val){
            return this.list(val);
        },
    pop:function(){}
}

var stack1 = new MyStack();       
stack1.insert(5);
var stack2 = new MyStack();       
stack2.insert(11);

【讨论】:

    【解决方案2】:

    您应该查看 John Resig 的 Simple Javascript Inheritance。这是一本很棒的读物,并且它已经扩展到为私人提供支持,恰当地称为Privates.js

    【讨论】:

    • 不知道 Privates.js。
    【解决方案3】:

    构造函数可以返回任何对象(不一定是this)。可以创建一个构造函数,它返回一个代理对象,其中包含对“真实”实例对象的“真实”方法的代理方法。这听起来可能很复杂,但事实并非如此;这是一个代码sn-p:

    var MyClass = function() {
        var instanceObj = this;
        var proxyObj = {
            myPublicMethod: function() {
                return instanceObj.myPublicMethod.apply(instanceObj, arguments);
            }
        }
        return proxyObj;
    };
    MyClass.prototype = {
        _myPrivateMethod: function() {
            ...
        },
        myPublicMethod: function() {
            ...
        }
    };
    

    如果我们定义一个命名受保护方法的约定,那么可以自动创建代理。我创建了一个小库,正是这样做的:http://idya.github.com/oolib/

    【讨论】:

    • 这对我来说非常奇怪——你能再解释一下吗?我也通读了你的 lib 文档并试图理解它,但我没有看到 proxyObj 对象在做什么
    • 您可以使用myObj = new MyClass(); 实例化MyClass。 myObj 将是 proxyObj:它将只有 1 个成员,称为 myPublicMethod。这是可以理解的,还是您还有其他问题?我很乐意提供帮助。
    【解决方案4】:

    我认为在您提到的两种方法中,当使用构造函数模式创建对象时,属性将被复制到其对象中。您提到的第一种方法是值得关注的。我觉得同样的方法也适用于第二种方法以及您对这种方法的关注。

    当我们想将“MyStack”的属性扩展到其他类时,我们通常会使用您提到的第二种方法。

    假设我想将您的类 MyStack 扩展到 MyTest,如下所示

    var dummy = function();
    dummy.prototype = MyStack.prototype;
    var MyTest = function(){
    };
    MyTest.prototype = new dummy(); // Assigning MyStack properties to MyTest
    var obj = new MyTest();
    

    【讨论】:

      猜你喜欢
      • 2017-03-06
      • 1970-01-01
      • 1970-01-01
      • 2016-02-13
      • 2012-03-20
      • 2013-10-12
      • 2016-12-26
      • 2012-03-13
      • 2017-10-09
      相关资源
      最近更新 更多