【发布时间】:2020-01-16 07:44:59
【问题描述】:
在尝试了解有关 Javascript(Google Apps 脚本风格)的更多信息时,我创建了一个我认为可能对许多项目有用的对象结构。这个小演示的主要目标是:
- 学习使用对象(类)和继承
- 通过在每个工作表中调用一次数据表来最大限度地减少对电子表格服务的调用
- 使用电子表格上的命名范围来访问表中的数据
下面的代码看起来很成功,但肯定可以改进。几个主要问题是:
- 有没有比这更好的方法来完成方法和属性的继承?
- Spreadsheet() 函数为每个工作表对象运行,从而导致环境结构在每个工作表对象中具有单独的“ss”和“namedRangeList”属性。这是正常的和预期的吗?还是有更好的方法来避免这种重复?或者,Javascript 只是记录指向这些对象的单个实例的指针,所以它们看起来是否重复并不重要?
- 因为它们对所有工作表都通用且相同,所以我曾预计“ss”和“namedRangeList”仅显示在环境级别,因此通过继承而不是复制可用于工作表。
- 还有哪些其他更改或方法可以提高我对类和对象的使用和理解?
这是我的代码的精简版本,它保留了结构的本质,但省略了 cmets、错误处理和其他功能。感谢您的 cmets 和帮助!
function Environment() {
this.title = 'Car & Driver';
this.ui = SpreadsheetApp.getUi();
this.dd = new Drivers();
this.cc = new Cars();
}
function Spreadsheet() {
this.ss = SpreadsheetApp.getActiveSpreadsheet();
this.namedRangeList = {};
var namedRanges = this.ss.getNamedRanges();
for (var i = 0; i < namedRanges.length; i++) {
var range = namedRanges[i].getRange();
this.namedRangeList[namedRanges[i].getName()] = {
sheet: range.getSheet().getSheetName(),
row: range.getRow(),
column: range.getColumn(),
rowCount: range.getNumRows(),
columnCount: range.getNumColumns(),
}
}
}
Spreadsheet.prototype = Object.create(Environment.prototype);
function Sheet() {
Spreadsheet.call(this);
this.sheet = this.ss.getSheetByName(this.sheetName);
this.data = this.sheet.getDataRange().getValues();
}
Sheet.prototype = Object.create(Spreadsheet.prototype);
function Cars() {
this.sheetName = 'Cars';
this.abbreviation = 'cc';
Sheet.call(this);
}
Cars.prototype = Object.create(Sheet.prototype);
function Drivers() {
this.sheetName = 'Drivers';
this.abbreviation = 'dd';
Sheet.call(this);
}
Drivers.prototype = Object.create(Sheet.prototype);
Sheet.prototype.idxOf = function(namedRange) {
return (this.namedRangeList[namedRange].rowCount == 1) ?
this.namedRangeList[namedRange].row - 1 :
this.namedRangeList[namedRange].column - 1;
}
function test_Environment() {
var env = new Environment();
env.ui.alert('The third driver is ' +
env.dd.data[3][env.dd.idxOf('ddFirst')] + ' ' + env.dd.data[3][env.dd.idxOf('ddLast')] + '.');
var tests = [
['dd', 2, 'ddLast' , 'Bailey' ],
['dd', 3, 'ddLicense' , 'pro' ],
['cc', 1, 'ccRadio' , 122.5 ],
['cc', 4, 'ccModel' , 'Corvette'],
];
tests.forEach(function(t) {
var v = env[t[0]].data[t[1]][env[t[0]].idxOf(t[2])];
Logger.log( (v == t[3]) + ': ' + (t[0] == 'dd' ? 'Driver ' : 'Car ') +
t[1] + ' ' + t[2].slice(2) + ' is ' + v );
});
env.ui.alert(env.title + ' is all done');
}
【问题讨论】:
-
对于代码审查问题,您应该在CodeReview 上发布。需要考虑的一件事:使用
classandextendssyntax。 -
虽然我同意这个问题在 Code Review 堆栈中更为常见,但在应用程序中脚本类尚未实现,因此在这种情况下你不能使用它。
-
@trincot Google Apps 脚本尚不支持这些。一些用户可以使用 v8 访问 beta 环境,但其余的都是 rhino
-
@op 你可以在调试时验证你的类对象都有
this.ss和this.namedRangeList的不同实例。您肯定会希望使用工厂方法,以便工厂为所有对象提供共享电子表格引用,并为同一工作表上的对象提供共享工作表引用。 (你最终会需要在工作表之间正确移动对象的逻辑) -
谢谢大家指点我Code Review。我已经在那里重新发布了我的问题。
标签: javascript object inheritance google-apps-script google-sheets