OO Javascript:将原型继承与私有变量结合起来的好方法?

Che*_*eso 4 javascript oop class-design

OO Javascript构造函数模式中:新古典与原型,我了解到使用原型继承的构造函数比使用所谓的neo-classical带闭包的模式的构造函数快10倍(或更多),如Crockford在他的"好零件"一书和演示文稿中所提出的那样.

由于这个原因,似乎更喜欢原型继承似乎是正确的事情.

问题有没有办法将原型继承与模块模式结合起来,以便在必要时允许私有变量?

我在想的是:

// makeClass method - By John Resig (MIT Licensed)
function makeClass(){
  return function(args){
    if ( this instanceof arguments.callee ) {
      if ( typeof this.init == "function" )
        this.init.apply( this, args.callee ? args : arguments );
    } else
      return new arguments.callee( arguments );
  };
}


// =======================================================

var User = makeClass();

// convention; define an init method and attach to the prototype
User.prototype.init = function(first, last){
  this.name = first + " " + last;
};


User.prototype.doWork = function (a,b,c) {/* ... */ }; 

User.prototype.method2= (function (a,b,c) {

    // this code is run once per class

    return function(a,b,c) {
        // this code gets run with each call into the method 
        var _v2 = 0;
        function inc() {
            _v2++;
        }

        var dummy = function(a,b,c) {
            /* ... */
            inc();
            WScript.echo("doOtherWork(" + this.name + ") v2= " + _v2);
            return _v2;
        };

        var x = dummy(a,b,c);
        this.method2 = dummy; // replace self
        return x;
    };

})();
Run Code Online (Sandbox Code Playgroud)

这不太对.但它说明了这一点.

有没有办法做到这一点,是否值得?

bob*_*nce 5

一般而言,更喜欢原型继承似乎是正确的

嗯......当然,这是用JavaScript做的更自然,本土感觉的事情.但是这么多JavaScript确实是错误的,这不一定是一种恭维!

当然,当性能不是问题时,获取每个方法自己的绑定副本的对象比共享其方法的对象更容易处理,因为您可以直接传递引用而object.method无需创建闭包委托或函数.bind.

有没有办法将原型继承与模块模式结合起来,以便在必要时允许私有变量?

你想从私有变量得到什么?如果它通过封装是一种Java风格的安全性概念,我会放弃它并且只是以Python方式执行:在成员名称的开头添加下划线,并且任何想要从外部使用的人都将被适当地警告它没有支持,可能搞砸了.在同一页面上执行的JavaScript代码中永远不会有安全边界,这样可以保证私有软件真正私密.

如果你想要的是避免在this调用方法时找到正确的副本,你可以在初始化器中手动绑定方法方法:

var Thing= makeClass();
Thing.prototype.init= function(a) {
    this._a= a;
    this.showA= this.showA.bind(this);
};
Thing.prototype.showA= function() {
    alert(this._a);
};

thing= new Thing(3);
setTimeout(thing.showA, 1000); // will work as `thing` has its own bound copy of `showA`
Run Code Online (Sandbox Code Playgroud)

(function.bind是future-JavaScript,你现在可以入侵Function.prototype,直到浏览器支持它.)

这自然会失去基于原型的对象的一些轻量级特性,但至少你仍然可以让它们共享不是方法的成员,以及永远不会被用作代理的方法,只要它清楚且你可以永远记住哪种方法可以用这种方式.

如果你只是想能够键入一个私有变量名而不必this.总是把它放在那里,是的,你必须用一个闭包来做.你的榜样世界可能会从初始化者那里得到一点清晰,而不是使用第一次自我写作:

var User= makeClass();
User.prototype.init= function(first, last){
    this.name= first+' '+last;
    this.method2= this._method2factory();
};
User.prototype._method2factory= function() {
    var _v2= 0;
    function inc() {
        _v2++;
    }

    return function method2(a,b,c) {
        /* ... */
        inc();
        WScript.echo('doOtherWork('+this.name+') v2= '+_v2);
        return _v2;
    };
};
Run Code Online (Sandbox Code Playgroud)

但我真的不知道该让你比较多的只是写this._v2this._inc().