JavaScript 内的物件都有内建的两个属性,可以实现对物件的存取,称为:
不同於一般物件内的属性,由 getter 和 setter 定义的属性有个专有名词称为 存取器属性 accessor property。
写在 getter 或 setter 的属性皆为方法,但在查找时,不需加上()
呼叫,背後会自动进行函式呼叫。
两者的差异?
getter 取值器,主要目的是读取值,不能进行赋值修改。
setter 设值器,可以设定属性的值,透过赋值的方式传入参数。
属性依照是否设置 setter 与 getter 分为三种特性:
在 JS 中有三种方法:
//物件实质中的写法
let obj = {
get name(){
....
},
set name(value){
...
}
}
setter、getter 可用来定义可计算属性 computed property,其值是每次存取时计算出来的,像是物件中若有属性 firstName 与 lastName,可以设置一个存取器属性 fullName ,透过 setter 设定将 firstName 与 lastName 属性相加印出。
❓ 我有疑问
其实可以在物件内建立一个方法就可以,为什麽要设置为 setter 呢?
根据忍者 2 的讲解,若某个值只依赖自物件的内部状态(如:firstName、lastName),比起以方法形式呈现,以属性的方式做读取其实更合理!
实际操作如下:
let aurther = {
firstName : 'Sherry',
lastName : 'Ho',
get fullName(){
consle.log(this.firstName + this.lastName)
},
set fullName(name){
let _name_ = name.split(' ')
this.firstName = _name_[0]
this.lastName = _name_[1]
}
}
aurther.fullName // SherryHo,呼叫 getter 取值
aurther.fullName = 'Sam Smith' // 重新指派值会呼叫 setter 将新值当参数传入
aurther.firstName // Sam,变为 setter 新赋的值
aurther.fullName // Sam Smith
在 DevTools 印出可以看到属於存取器属性前会加上 setter 与 getter 字样。
在 class
内加上 set 和 get 关键字,就可以定义存取器属性。
// class 内写法
class Name{
construcor(){}
set name(){}
get name(value){}
}
举例:
定义一个 class 名称为 Cake,设置一个可读写的属性 producer,这个存取器属性会存入 prototype 物件内,以 Cake 创建的实例可以透过原型链取得。
class Cake {
constructor(flavor){
this.flavor = flavor;
this._producer = 'Hoo'
}
set producer(name){
this._producer = name;
}
get producer(){
return this._producer;
}
}
let cake1 = new Cake('Tiramisu')
cake1.producer // Hoo,实例可透过原型链取得 producer 属性
在 DevTools 中印出可以看到,存取器属性 producer 存在於 prototype 内
透过 Object.defineProperty 可以定义或修改物件中的属性。
Object.defineProperty(目标物件,'特性名称', {setter, getter 描述})
let cake = {};
Object.defineProperty(cake, 'producer', {
get: function (){
return this.producer
},
set: function (name){
this.producer = name;
}
})
可以透过 Object.defineProperty 来控制存取私有变数,与物件实质和 class 不同的是,透过 Object.defineProperty 会和私有变数建立在相同的范围中!
function Cake() {
let _cakeRating = 0;
Object.defineProperty(this, 'cakeRating', {
get: ()=>{
return _cakeRating;
},
set: (value)=>{
_cakeRating = value;
}
})
}
let cake1 = new Cake();
cake1.cakeRating = 10; // 透过 getter 指派值给 _cakeRating 变数
console.log( cake1.cakeRating ) // 10,只能透过 getter 取到 _cakeRating 这个私有变数
若对 getter 属性重新赋值,在一般模式下不会产生效果,引擎会自动忽略这项动作,但在严格模式下禁止这项动作,会抛出错误提醒不能对唯读属性修改。
'use strict'
class Cake {
constructor(flavor){
this.flavor = flavor;
this._productionDate = 'Oct.3, 2021'
}
set productionDate(date){
this._productionDate = date;
}
get producer(){
return 'this.Hoo';
}}
let cake1 = new Cake('cream')
a.producer = 'sherry' // error! Cannot set property producer of #<Cake> which has only a getter
008重新认识 JavaScipt
忍者 JavaScript 开发技巧探秘第二版 by John Resig, Bear Bibeault, Josip Maras
MDN
<<: JavaScript Call, Bind, Apply
>>: 【day19】聊天室(下) X Realtime database
环境 VS2013 ASP.NET 4.0 GridView怎麽做删除钮与编辑钮. 要做之前,我们要...
今天心情郁闷只好来写一些特别的东西,来跟大家聊聊空服的外站人生。 还记得那是一个很冷很冷的冬天,历经...
今天来练习切这个版面 运用到的观念 flexbox box model 区块大小的计算 margin...
安装环境第一步骤 App Store 搜寻Xcode并下载 下载後并创立一个专案 进入後系统帮我们预...
前言 参考文件: https://kubernetes.io/docs/tasks/access-a...