javascript 一个班中的一个班?

xghobddn  于 2023-03-21  发布在  Java
关注(0)|答案(3)|浏览(118)

理想情况下,我想做的事情如下:

class Chess = {
  constructor() {
    this.board = ...;
    ...
  };

  class Square = {
    constructor(row, col) {
      this.row = row;
      this.col = col;
  };
};

我的主要动机是,与国际象棋和广场类分别定义如下:(指国际象棋课)

this.empty(square)

可以缩短为

square.empty()

其可读性更强且更简洁。
不幸的是我不能

Square.empty()

方法,因为结果取决于Chess类中的信息,并且

square.empty(chess)

并没有什么真实的性的改善。
我有一个Square类的原因是

square.up()

似乎比

[row, col + 1]

你对我如何完成上面的工作有什么建议吗?是在一个类中写一个类,还是完全写其他的?
编辑:
根据Likle和Alex的建议,我做了以下事情:
我向类广场添加了一个上下文属性

class Square = {
  constructor(context, row, col) {
    this.context = context;
    this.row = row;
    this.col = col;
  };
};

然后将Chess.prototype中的一些方法重新定义为Square.prototype。例如:

// before
Chess.prototype.empty = function (square) {
  return this.piece(square) === 0;
};

// after
Square.prototype.empty = function () {
  return this.piece() === 0;
};

这意味着每次创建Square对象时,我都需要添加上下文。例如:

new Square(3, 4); // before
new Square(this, 3, 4); // after
new Square(this.context, 3, 4); // sometimes like this

为了使代码更易读,我创建了以下方法:

Chess.prototype.createSquare = function (row, col) {
  return new Square(this, row, col);
};

因此,有时可以使用以下命令创建Square对象

this.createSquare(3, 4);
bf1o4zei

bf1o4zei1#

有人可能会说JavaScript本身没有“嵌套”类--例如,类无法使用父类作用域,除了访问父类属性(static元素)之外,它对任何事情都没有意义。
JavaScript中的类和其他类一样只是一个对象,所以你也可以定义一个类,然后用另一个类的属性来引用它:

class Chess {
}

Chess.Square = class {
};

(yes类的名称是可选的--在上面,Chess上的Square属性引用了一个 * 没有名称 * 的类;对于调试和内省来说不一定很好,但只是在这里说明一点)
有了上面的内容,你可以做如下事情:

new Chess.Square();

一般来说,你对一个类或一个类的对象所做的一切--new只是期望一个函数充当构造函数,而class声明实际上在程序运行时“衰减”为构造函数--以下所有表达式的值都是true:

Chess instanceof Function;
typeof Chess == "function";
Chess.Square instanceof Function;
typeof Chess.Square == "function";
Chess.prototype.constructor == Chess;
Chess.Square.prototype.constructor == Chess.Square;

所以嵌套的 constructors,那么--现在我们已经确定JavaScript类本质上是它的构造函数。好吧,ECMAScript与每个类都有 * 一些 * 额外的元数据,以及 * 一些 * 差异,但它对嵌套构造函数访问外部作用域没有负面影响:

function Chess() {
    const chess = this;
    function Square() { /// Obviously, this function/constructor/class is only available to expressions and statements in the Chess function/constructor/class (and if explicitly "shared" with other code).
        Chess; /// Refers to the outer constructor/class -- you can do `new Chess()` etc
        this; /// Refers to this Square object being created
        chess; /// Refers to what `chess` declared outside this method, refers to at the time of creating this Square object
    }
}

上面使用了所谓的“闭包”,这需要你很好地掌握JavaScript中的 scoping 是如何工作的。在Java中,上面指定的Square类被称为嵌套的 instance 类,而不是嵌套的 static 类。答案最上面的第一个例子,使用class关键字,确实指定了后者的形式,though(一个“静态”类)。
下面是另一种定义“示例”类Square的方法:

class Chess {
    constructor() {
        this.Square = class {
            constructor() {
                /// Be vigilant about `this` though -- in every function (except arrow functions) `this` is re-bound, meaning `this` in this constructor refers to an instance of the anonymous class, not to an instance of the `Chess` class; if you want to access the latter instance, you must have a reference to it saved for this constructor to access, e.g. with the `const chess = this;` statement in `Chess` constructor somewhere
            }
        }; /// Every `Chess` object gets a _distinct_ anonymous class referred to with a property named `Square`; is a class for every object expensive? is it needed? is it useful?
    }
}

JavaScript的特点是,不管是好是坏,它可以以多种方式实现OOP,当然比其他一些“OOP语言”所允许的要多,而且“嵌套类”对不同的人来说可能意味着不同的东西,在不同的项目中。这被称为“有很多绳子可以吊死自己”--有很多工具可以帮助你优雅地实现你想要的模型,和/或使你的代码难以阅读(特别是对那些不像你一样了解JavaScript的人)和调试。这是一个在使用“嵌套类”之前需要解决的权衡。

xzv2uavs

xzv2uavs2#

目前,有are no nested classes。你可以做的是有两个单独的类,ChessChessSquare-并在ChessSquare的构造函数中传递一个对chess的引用,并将其存储为属性。这样你就不必在ChessSquare的方法中传递它:

class ChessSquare = {
    constructor(chess, row, col) {
      this.chess = chess;
      this.row = row;
      this.col = col;
    }

    empty() {
      // "this.chess" references the chess, and "this" references the square.
    }
  };

您可能希望在Chess类本身中创建ChessSquare的所有示例。

3duebb1j

3duebb1j3#

下面的代码运行得很好:

class Chess  {
  constructor() {
    this.board = {}
    for (var i=0; i<8; i++) {
          for (var j=0; j<8; j++) {
               this.board[i,j] = new Square(i,j)
               }
          }

  };

};

class Square {
    constructor(row, col) {
      this.row = row;
      this.col = col;
      this.color = "black"
      if ((row+col)%2 == 1) this.color = "white"
  };
};

这两个独立的类在Chess(main?)类中通过直接调用Square类而相互关联,因此在Chess示例化时,棋盘方格也被定义。

相关问题