在JavaScript中构建类的正确方法?

时间:2011-05-13 15:13:21

标签: javascript prototype-programming

我是JavaScript的新手,并试图理解我应该如何编写类(我的背景是'常规'OO语言,例如java和c ++。)

我知道我有两种选择:

  1. 如果我希望我的班级拥有私人方法和成员,我无法在原型中定义它们。但在这种情况下,它们将为每个创建的新对象(内存问题)构建。

  2. 如果我在类原型中定义方法,我将没有封装(这对我来说很奇怪,作为java / c ++开发人员:P)。

  3. 您使用的两种方法中的哪一种?为什么呢?

3 个答案:

答案 0 :(得分:7)

所以,我不认为对这个问题有“正确答案”......这基本上是你喜欢的,并且认为最适合你的特定用途。我的许多课程都是“静态课程”,例如

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

因为我永远不需要实例化它们。当我需要实例化多个实例时,我使用原型方法。

如果您需要私有变量,您可以定义一个函数/类来执行私有变量,以及需要访问该函数/类中的私有变量的方法。然后,对不需要访问私有变量的所有方法使用prototype方法。 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");
}

同时执行这两个操作应该可以让您的实例化更轻一些,但仍然会给您一些封装。到目前为止,我从未打扰私人变种。

答案 1 :(得分:0)

如果您正在使用原型框架,那么最好使用它们实现类和继承的方式。你可能指的是this article

通常我不认为私人会员在javascript中使用。 (编辑:不是在实例化的类中。我经常看到我们的代码库中有一些“模块”,这些模块确实拥有一个私有状态,但可以看作是单例)

凯文的回答几乎总结了一下。在技​​术上可以解决语言缺乏封装的问题,但是如果要对类进行大量实例化,则需要付出代价。此外,如果您要使用继承,我认为您需要一些工作才能获得受保护的可见性。

例如,在查看ext源时,我认为没有看到任何私有内容。他们确实将“// private”放在应该是私有的方法上,这暗示不应该直接调用它们。 它确实意味着如果你要以这种方式编码,你需要更多的“纪律”来编写getter / setter。

答案 2 :(得分:0)

为什么现在有。现在。

上述答案对他们的时间是正确的。

以下是解决方案:

'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' } }