getter = special method that makes a property readable
setter = special method that makes a property writeable
validate and modify a value when reading/writing a property
class Rectangle{
constructor(width, height){
// 使用下划线开头表示“内部属性”,避免和 getter/setter 混淆
// 这里的“内部属性” 只是命名方式
this._width = width;
this._height = height;
}
// setter:设置宽度
set width(newWidth){
if(newWidth > 0){ // 只允许正数
this._width = newWidth; // ✅ 更新内部属性
}
else{
console.log("Width must be a positive number");
}
}
// setter:设置高度
set height(newHeight){
if(newHeight > 0){
this._height = newHeight; // ✅ 更新内部属性
}
else{
console.log("Height must be a positive number");
}
}
// getter:获取宽度(读取时自动调用)
get width(){
return `width is ${this._width}`;
}
// getter:获取高度
get height(){
return `height is ${this._height}`;
}
// getter:计算面积(只读属性)
get area(){
// toFixed(1) 保留一位小数
return `area is ${(this._width * this._height).toFixed(1)}`;
}
}
// ================== 测试 ==================
const rectangle = new Rectangle(3, 4);
// 使用 setter 修改属性
rectangle.width = 18; // ✅ setter 会检查数值是否大于 0
rectangle.height = 5;
// 使用 getter 获取属性(看起来像属性,其实调用的是函数)
console.log(rectangle.width); // "width is 18"
console.log(rectangle.height); // "height is 5"
// 调用 area getter,计算面积
console.log(rectangle.area); // "area is 90.0"another example:
class Person{
constructor(firstName, lastName, age){
// ⚠️ 注意:这里写的是 this.firstName = firstName
// 实际上并不是直接赋值,而是会调用 set firstName()
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
// =================== Setter(设值器) ===================
// 当你给 person.firstName 赋值时,会自动触发这个函数
set firstName(newFirstName){
// 检查传入值必须是 string 并且非空
if (typeof newFirstName === "string" && newFirstName.length > 0) {
this._firstName = newFirstName; // ✅ 使用内部变量 _firstName 存储
}
else{
console.error("first name must be a non-empty string");
}
}
set lastName(newLastName){
if (typeof newLastName === "string" && newLastName.length > 0) {
this._lastName = newLastName; // ✅ 存储到 _lastName
}
else{
console.error("last name must be a non-empty string");
}
}
set age(newAge){
if (typeof newAge === "number" && newAge >= 0) {
this._age = newAge; // ✅ 存储到 _age
}
else{
console.error("age must be a non-negative number");
}
}
// =================== Getter(取值器) ===================
// 当你访问 person.firstName 时,会执行这个函数
get firstName(){
return this._firstName;
}
get lastName(){
return this._lastName;
}
// fullName 没有对应的 setter,只能读取
// 它是一个 "计算属性",通过 _firstName + _lastName 动态生成
get fullName(){
return this._firstName + " " + this._lastName;
}
get age(){
return this._age;
}
}
// =================== 测试 ===================
// 这里初始化传错了类型:
// 420 (number) -> firstName ❌ (需要 string)
// 69 (number) -> lastName ❌ (需要 string)
// "pizza" (string) -> age ❌ (需要 number)
// 所以 constructor 会调用 setter,但失败并报错
const person = new Person(420, 69, "pizza");
// ✅ 这里重新赋值,触发 setter,成功写入
person.firstName = "spongebob";
person.lastName = "squarepants";
person.age = 30
// ✅ 读取属性时,触发 getter,输出内部存储的值
console.log(person.firstName); // spongebob
console.log(person.lastName); // squarepants
console.log(person.age); // 30