【问题标题】:Correct way to build classes in JavaScript?在 JavaScript 中构建类的正确方法?
【发布时间】:2011-08-25 00:57:24
【问题描述】:

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

我知道我有两种选择:

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

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

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

【问题讨论】:

标签: javascript prototype-programming


【解决方案1】:

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

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

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

如果您需要私有变量,您可以定义一个函数/类来执行私有变量,以及需要在该函数/类中访问这些私有变量的方法。然后,对所有不需要访问私有变量的方法使用原型方法。例如

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");
}

两者都做应该能让你的实例化更轻一些,但仍然给你一些封装。到目前为止,我从来没有为私有变量烦恼过。

【讨论】:

    【解决方案2】:

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

    通常我认为私有成员不会在 javascript 中使用。 (编辑:不在实例化类中。我经常在我们的代码库中看到一些“模块”,它们确实保持私有状态,但可以被视为单例)

    Kevin 的回答非常概括。技术上可以解决语言缺乏封装的问题,但如果你的类要被实例化很多,这是有代价的。此外,我认为如果您要使用继承,您需要做一些工作来获得受保护的可见性。

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

    【讨论】:

      【解决方案3】:

      为什么是的,现在有……。

      上面的答案在当时是正确的。

      这是新的解决方案:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-01
        • 2013-08-04
        • 2015-04-15
        • 1970-01-01
        • 1970-01-01
        • 2016-09-23
        • 2012-09-28
        • 2013-08-19
        相关资源
        最近更新 更多