Dav*_*vid 7 javascript oop nested class
理想情况下,我想做类似以下的事情:
class Chess = {
constructor() {
this.board = ...;
...
};
class Square = {
constructor(row, col) {
this.row = row;
this.col = col;
};
};
Run Code Online (Sandbox Code Playgroud)
我的主要动机是,将 Chess 和 Square 类分别定义为:(这指的是 Chess 类)
this.empty(square)
Run Code Online (Sandbox Code Playgroud)
可以缩短为
square.empty()
Run Code Online (Sandbox Code Playgroud)
这更具可读性和更简洁。
不幸的是我不能只做一个
Square.empty()
Run Code Online (Sandbox Code Playgroud)
方法,因为结果取决于 Chess 类中的信息,并且
square.empty(chess)
Run Code Online (Sandbox Code Playgroud)
是没有真正的改善。
我有 Square 课程的原因是这样的
square.up()
Run Code Online (Sandbox Code Playgroud)
看起来比类似的东西好得多
[row, col + 1]
Run Code Online (Sandbox Code Playgroud)
您对我如何实现上述目标有什么建议吗?有什么方法可以在类中编写类或者完全是其他东西吗?
编辑:
根据 likele 和 alex 的建议,我做了以下事情:
我向 Class Square 添加了一个上下文属性
class Square = {
constructor(context, row, col) {
this.context = context;
this.row = row;
this.col = col;
};
};
Run Code Online (Sandbox Code Playgroud)
然后将Chess.prototype中的一些方法重新定义到Square.prototype中。例如:
// before
Chess.prototype.empty = function (square) {
return this.piece(square) === 0;
};
// after
Square.prototype.empty = function () {
return this.piece() === 0;
};
Run Code Online (Sandbox Code Playgroud)
这意味着每次我创建 Square 对象时,我都需要添加上下文。例如:
new Square(3, 4); // before
new Square(this, 3, 4); // after
new Square(this.context, 3, 4); // sometimes like this
Run Code Online (Sandbox Code Playgroud)
为了使代码更具可读性,我创建了以下方法:
Chess.prototype.createSquare = function (row, col) {
return new Square(this, row, col);
};
Run Code Online (Sandbox Code Playgroud)
因此,有时可以使用以下命令创建 Square 对象
this.createSquare(3, 4);
Run Code Online (Sandbox Code Playgroud)
有人可能会争辩说 JavaScript 没有“嵌套”类——例如,类无法使用父类作用域,除了访问父类属性(元素)之外,它对其他任何事情都没有意义static
。
JavaScript 中的类只是一个像其他对象一样的对象,因此您也可以定义一个类并使用另一个类上的属性引用它:
class Chess {
}
Chess.Square = class {
};
Run Code Online (Sandbox Code Playgroud)
(是的,类的名称是可选的——上面的Square
属性 on指的是没有名称Chess
的类;不一定非常适合调试和内省,但只是在这里说明一点)
有了上述内容,您就可以执行以下操作:
new Chess.Square();
Run Code Online (Sandbox Code Playgroud)
一般来说,您对类或类的对象所做的所有其他操作 -new
只是期望一个函数充当构造函数,并且class
当程序运行时声明实际上“衰减”为构造函数 - 以下所有表达式的值都是真的:
Chess instanceof Function;
typeof Chess == "function";
Chess.Square instanceof Function;
typeof Chess.Square == "function";
Chess.prototype.constructor == Chess;
Chess.Square.prototype.constructor == Chess.Square;
Run Code Online (Sandbox Code Playgroud)
既然我们已经确定 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
}
}
Run Code Online (Sandbox Code Playgroud)
上面使用了所谓的“闭包”,这要求您很好地掌握JavaScript 中作用域的工作原理。在 Java 中,Square
上面指定的类被称为嵌套实例类,而不是嵌套静态类。答案最顶部的第一个示例,使用class
关键字,确实指定了后者的形式(“静态”类)。
这是定义“实例”类的另一种方法Square
:
class Chess {
}
Chess.Square = class {
};
Run Code Online (Sandbox Code Playgroud)
JavaScript 的问题在于,无论好坏,它都可以用不止一种方式实现 OOP,当然比其他一些“OOP 语言”允许的方式更多,并且“嵌套类”可能意味着不同的事情,针对不同的人,在不同的程序中。这被称为“有很多绳子可以吊死自己”——很多设施可以帮助你优雅地实现你想要的模型,和/或使你的代码难以阅读(特别是对于那些不知道的人来说)和你一样多的 JavaScript)和调试。在全力以赴使用“嵌套类”之前,这是一个需要解决的权衡问题。
目前,没有嵌套类。您可以做的是拥有两个单独的类,Chess
并且ChessSquare
- 并在 的构造函数中传递对国际象棋的引用ChessSquare
,并将其存储为属性。这样您就不必在以下方法中传递它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.
}
};
Run Code Online (Sandbox Code Playgroud)
您可能想在类本身ChessSquare
内创建 的所有实例Chess
。
归档时间: |
|
查看次数: |
10577 次 |
最近记录: |