Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
678 views
in Technique[技术] by (71.8m points)

oop - JavaScript Classes

I understand basic JavaScript pseudo-classes:

function Foo(bar) {
    this._bar = bar;
}

Foo.prototype.getBar = function() {
    return this._bar;
};

var foo = new Foo('bar');
alert(foo.getBar()); // 'bar'
alert(foo._bar); // 'bar'

I also understand the module pattern, which can emulate encapsulation:

var Foo = (function() {
    var _bar;

    return {
        getBar: function() {
            return _bar;
        },
        setBar: function(bar) {
            _bar = bar;
        }
    };
})();

Foo.setBar('bar');
alert(Foo.getBar()); // 'bar'
alert(Foo._bar); // undefined

But there are un-OOP-like properties to both of these patterns. The former does not provide encapsulation. The latter does not provide instantiation. Both patterns can be modified to support pseudo-inheritance.

What I'd like to know is if there is any pattern that allows:

  • Inheritance
  • Encapsulation (support for "private" properties/methods)
  • Instantiation (can have multiple instances of the "class", each with its own state)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

what about this :

var Foo = (function() {
    // "private" variables 
    var _bar;

    // constructor
    function Foo() {};

    // add the methods to the prototype so that all of the 
    // Foo instances can access the private static
    Foo.prototype.getBar = function() {
        return _bar;
    };
    Foo.prototype.setBar = function(bar) {
        _bar = bar;
    };

    return Foo;
})();

And now we have instantiation, encapsulation and inheritance.
But, there still is a problem. The private variable is static because it's shared across all instances of Foo. Quick demo :

var a = new Foo();
var b = new Foo();
a.setBar('a');
b.setBar('b');
alert(a.getBar()); // alerts 'b' :(    

A better approach might be using conventions for the private variables : any private variable should start with an underscore. This convention is well known and widely used, so when another programmer uses or alters your code and sees a variable starting with underscore, he'll know that it's private, for internal use only and he won't modify it.
Here's the rewrite using this convention :

var Foo = (function() {
    // constructor
    function Foo() {
        this._bar = "some value";
    };

    // add the methods to the prototype so that all of the 
    // Foo instances can access the private static
    Foo.prototype.getBar = function() {
        return this._bar;
    };
    Foo.prototype.setBar = function(bar) {
        this._bar = bar;
    };

    return Foo;
})();

Now we have instantiation, inheritance, but we've lost our encapsulation in favor of conventions :

var a = new Foo();
var b = new Foo();
a.setBar('a');
b.setBar('b');
alert(a.getBar()); // alerts 'a' :) 
alert(b.getBar()); // alerts 'b' :) 

but the private vars are accessible :

delete a._bar;
b._bar = null;
alert(a.getBar()); // alerts undefined :(
alert(b.getBar()); // alerts null :(

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...