JavaScript 基础
Document
运算符
深入数据和类型
函数进阶
原型、继承
类
浏览器存储
Web API
事件
错误处理
异步编程
网络请求
模块
练习
实例
工具与规范
软件架构模式
设计模式
简而言之, getter
和 setter
访问器能让我们像使用属性一样使用方法。
getter
如果我们定义了一个对象,有 firstname
、 lastname
、 fullname
。 那么每次设置 firstname
或 lastname
时,同时去设置 fullname
就会很蠢。
$$jsdemo$$
$$edit$$
let person = {
firstname: "艾伦",
lastname: "耶格尔",
fullname: "艾伦·耶格尔",
}
console.log(person) // {firstname: '艾伦', lastname: '耶格尔', fullname: '艾伦·耶格尔'}
// 修改 lastname 要同时修改 fullname
person.lastname = "耶路撒冷"
person.fullname = "艾伦·耶路撒冷"
console.log(person) // {firstname: '艾伦', lastname: '耶路撒冷', fullname: '艾伦·耶路撒冷'}
实际上我们的 fullname
可以由 lastname
得出,无需额外保存,已然出现了冗余。所以我们可以用 getFullname
方法代替 fullname
。
$$tip
数据库的设计中有设计三范式的概念,和这里的场景挺类似,说的就是数据不应出现冗余。
$$
$$jsdemo$$
$$edit$$
let person = {
firstname: "艾伦",
lastname: "耶格尔",
getFullname() {
return this.firstname + "·" + this.lastname
},
}
alert(person.getFullname()) // 艾伦·耶格尔
// 修改 lastname 无需设置 fullname
person.lastname = "耶路撒冷"
alert(person.getFullname()) // 艾伦·耶路撒冷
getter
访问器就出现了,定义一个 getter
使用的是 get
关键字,我们能像访问一个属性一样使用方法。
$$jsdemo$$
$$edit$$
let person = {
firstname: "艾伦",
lastname: "耶格尔",
get fullname() {
return this.firstname + "·" + this.lastname
},
}
// 注意这是一个属性,不用加括号
alert(person.fullname) // 艾伦·耶格尔
// 修改 lastname 无需设置 fullname
person.lastname = "耶路撒冷"
alert(person.fullname) // 艾伦·耶路撒冷
setter
fullname
这时只能获取值,有时我们也希望能直接通过赋值 fullname
来修改 firstname
和 lastname
。
$$jsdemo$$
$$edit$$
let person = {
firstname: "艾伦",
lastname: "耶格尔",
get fullname() {
return this.firstname + "·" + this.lastname
},
set fullname(value) {
let names = value.split("·")
this.firstname = names[0]
this.lastname = names[1]
},
}
// 注意这是一个属性,不用加括号
alert(person.fullname) // 艾伦·耶格尔
person.fullname = "艾伦·耶路撒冷"
alert(person.lastname) // 耶路撒冷
当然,一个校验也是不可少的。
$$jsdemo$$
$$edit$$
let person = {
firstname: "艾伦",
lastname: "耶格尔",
get fullname() {
return this.firstname + "·" + this.lastname
},
set fullname(value) {
if (!value.includes("·")) {
alert("请使用合法的 fullname")
} else {
let names = value.split("·")
this.firstname = names[0]
this.lastname = names[1]
}
},
}
// 注意这是一个属性,不用加括号
alert(person.fullname) // 艾伦·耶格尔
person.fullname = "艾伦耶路撒冷" // 请使用合法的 fullname
alert(person.lastname) // 耶格尔
练习
- 设计一个对象,能够处理以下操作。
let wedding = {
// 补全这里
}
wedding.date = "2020年10月20日"
alert(
`那是${wedding.year}年的时候,${wedding.month}月的天气有些寒冷,${wedding.day}号的下午我和你妈妈举行了婚礼。`
) // 那是2020年的时候,10月的天气有些寒冷,20号的下午我和你妈妈举行了婚礼。
$$answer 答案一:
赋值时直接使用 setter
访问器。
$$jsdemo$$
$$edit$$
let wedding = {
year: null,
month: null,
day: null,
set date(value) {
let yearIdx = value.indexOf("年")
let monthIdx = value.indexOf("月")
let dayIdx = value.indexOf("日")
this.year = parseInt(value.substring(0, yearIdx))
this.month = parseInt(value.substring(yearIdx + 1, monthIdx))
this.day = parseInt(value.substring(monthIdx + 1, dayIdx))
},
get date() {
return `${this.year}年${this.month}月${this.day}日`
},
}
wedding.date = "2020年10月20日"
alert(
`那是${wedding.year}年的时候,${wedding.month}月的天气有些寒冷,${wedding.day}号的下午我和你妈妈举行了婚礼。`
) // 那是2020年的时候,10月的天气有些寒冷,20号的下午我和你妈妈举行了婚礼。
答案二:
获取值时再使用 getter
访问器。
$$jsdemo$$
$$edit$$
let wedding = {
date: null,
get year() {
let yearIdx = this.date.indexOf("年")
return parseInt(this.date.substring(0, yearIdx))
},
get month() {
let yearIdx = this.date.indexOf("年")
let monthIdx = this.date.indexOf("月")
return parseInt(this.date.substring(yearIdx + 1, monthIdx))
},
get day() {
let monthIdx = this.date.indexOf("月")
let dayIdx = this.date.indexOf("日")
return parseInt(this.date.substring(monthIdx + 1, dayIdx))
},
}
wedding.date = "2020年10月20日"
alert(
`那是${wedding.year}年的时候,${wedding.month}月的天气有些寒冷,${wedding.day}号的下午我和你妈妈举行了婚礼。`
) // 那是2020年的时候,10月的天气有些寒冷,20号的下午我和你妈妈举行了婚礼。
$$