我有一个包含私有属性的类,这是一个数组。有一个公共getter和setter来确保数据操作触发所需的业务逻辑。
当调用者能够设置私有属性而不运行公共setter中包含的关联逻辑时,我遇到了一个问题。
我用这个简单的代码重现了这个问题:
class Greeter {
private _greetings: string[];
constructor () {}
set greetings(greetings: string[]) {
let newGreetings: string[] = [];
for (let i: number = 0; i < greetings.length; i++) {
newGreetings.push("setter_" + greetings[i] )
}
this._greetings = newGreetings;
}
get greetings() {
return this._greetings;
}
}
let greeter = new Greeter();
greeter.greetings = ["test"];
let test1 = document.createElement('p');
test1.textContent = greeter.greetings[0];
document.body.appendChild(test1);
greeter.greetings[0] = "test";
let test2 = document.createElement('p');
test2.textContent = greeter.greetings[0];
document.body.appendChild(test2);
要查看TS游乐场中的代码,请按以下链接:
我的问题是:我做错了吗?这是预期的行为吗?或者这更像是一个打字稿编译器的问题,它不应该允许这个代码编译?
答案 0 :(得分:1)
具体看这两行:
greeter.greetings = ["test"];
和
greeter.greetings[0] = "test"
它们看起来很相似,但它们确实非常不同。这一行说明将greetings
的{{1}}属性设置为greeter
。我们会调用["test"]
setter,因为我们正在设置greetings
属性。
greetings
相反,这条线应该被认为是两个操作
greeter.greetings = ["test"];
正如您所看到的,我们不会设置 // this line...
greeter.greetings[0] = "test"
// ...is the same as
const tmp = greeter.greetings;
tmp[0] = "test";
属性,我们获取它!然后我们设置数组的属性。 <{1}} setter未使用。
从TypeScript 2.0开始(在撰写本文时为测试版),您将能够使用greetings
来表示可以读取但不能写入的数组。这样,您就可以向消费者展示greetings
,但会定期ReadonlyArray<string>
作为ReadonlyArray<string>
字段。