开发者

Correct way to build classes in JavaScript?

开发者 https://www.devze.com 2023-03-05 12:29 出处:网络
I am new to JavaScript, and trying to understand how i should write classes (my background in \'regular\' OO languages, such as java and c++).

I am new to JavaScript, and trying to understand how i should write classes (my background in 'regular' OO languages, such as java and c++).

I understand that i have two options:

  1. If i want my class to have private methods and members i can't define them in the prototype. But in that case, they will be built for each new object created (memory issue).

  2. If i define methods in the class prototype, i will have no encapsulation (this is weird for me, as a java/c++ developer :P).

Which of the two methods y开发者_StackOverflow中文版ou use? why?


So, I don't think there's a "right answer" to this question...it's basically what you prefer and think is best for your particular use. Many of my classes are "Static classes", e.g.

var MyClassName = {
    methodName: function() { },
    //...
}

As I never need to instantiate them. When I need to instantiate multiple instances, I use the prototype method.

If you NEED private variables, you could define a function/class to do private variables, and the methods that need to access those private vars within that function/class. Then, use the prototype method for all methods that don't need access to the private vars. E.g.

var PageClass = function() {
    var _birthdate;

    this.getBirthdate = function() {
        return typeof(_birthdate) == "undefined" ? null : _birthdate;
    }
    this.setBirthdate = function( date ) {
        if( typeof(date) == 'object' && date.constructor == Date ) {
            _birthdate = date;
        }
        else {
            throw "Invalid Argument Exception: PageClass.setBirthdate expects parameter of type 'Date'";
        }
    }
}
PageClass.prototype.doSomething = function() {
    alert("DOING SOMETHING");
}

Doing both should enable you to keep your instantiation a bit lighter weight, but still give you some encapsulation. So far, I've never bothered with private vars.


If you're using the prototype framework you'll be better off using their way of implementing classes and inheritance. You were probably referring to this article

Usually I don't think private members are used in javascript. (edit: Not in instantiated classes. I see quite regularly some "modules" in our codebase which do hold a private state but could be seen as singletons)

Kevin's answer pretty much sums it up. It is technically possible to work around the language's lack of encapsulation, but it comes at a cost if your class is going to be instantiated a lot. Also I think you'd need some work to get a protected visibility if you're going to use inheritance.

I don't think I saw any private stuff when looking at the ext sources for example. They do put "//private" over methods that should be private, which is a hint that they shouldn't be called directly. It does mean that you need more "discipline" to write getters/setters if you're going to code this way.


Why yes there is ... now.

The answers above are correct for their time.

Here is the new solution:

'use strict';

// Declare our class
class Metadata {

    // Declare the constructor and pass it some values - a and b are "defaults"
    constructor( ninfo, a = 1.0, b = 1.0 )
    {
        // Set our class variables
        this.ninfo = ninfo;
        this.a = a;
        this.b = b;

        // Define our "secret" or nonenumerable options
        Object.defineProperty( this, 'addA', {
            enumerable: false,
            writable: false,

            // Have it add our passed in value
            value: n => this.a += n
        } );
    }
}

// Call our class and pass in some variables
let x = new Metadata( "we have a and b", 1.0 );

// Log our result if we call "addA"
console.log( x.addA( 3 ) ); // => 4

// Log our object
console.log( x ); // => Metadata { ninfo: 'we have a and b', a: 4, b: 2 }

// Log our object 'for real'
console.log( require( 'util' ).inspect( x, { showHidden: true, depth: null } ) );

// result
// Metadata {
//      ninfo: 'we have a and b',
//      a: 4,
//      b: 2,
//      [addA]: { [Function: value] [length]: 1, [name]: 'value' } }
0

精彩评论

暂无评论...
验证码 换一张
取 消