文章目录
一、使用getter和setter控制访问对象的属性
我们可以使用普通的自定义的getter和setter方法来控制对属性的访问。
// 普通的getter和setter,需要显示地调用相关的方法
function Person() {
let age = 10;// 当做私有属性来用
this.getAge = function () {
console.log("获取属性值:");
return age;
}
this.setAge = function (value) {
console.log('设置属性值:', value);
age = value;
}
}
let p1 = new Person();
console.log(p1.getAge());
p1.setAge(20);
console.log(p1.getAge());
上边代码中,我们所有与age属性交互的地方都必须显示地调用相关的方法。JavaScript支持真正的getter和setter用于访问普通的数据属性。
在JavaScript中,可以通过两种方式定义getter和setter。
- 通过对象字面量定义,或者在ES6的class中定义
- 通过使用内置的Object.defineProperty()方法来定义
1、在对象字面量中定义getter和setter
- 在属性名前添加get关键字定义getter方法,getter方法不接受任何参数
- 在属性名前添加set关键字定义setter方法,setter方法接受一个参数
- 获取属性值将隐式调用getter方法,设置属性值将隐式调用setter方法
let obj = {
names: ['小明', '小红'],
get firstName() {
console.log('获取第一个人名'); // 可以进行一些日志记录
return this.names[0];
},
set firstName(value) {
console.log('设置第一个人名');
this.names[0] = value;
}
}
console.log(obj.firstName); // 把firstName当做属性进行操作
obj.firstName = '小黑';
console.log(obj.firstName);
2、在ES6的class中定义getter和setter
在“类”的内部可以使用 get
和 set
关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
// ES6的class中的getter和setter
class Student {
constructor() {
this.names = ['小明', '小红'];
}
get firstName() {
console.log('get firstname');
return this.names[0];
}
set firstName(value) {
console.log('set firstname');
this.names[0] = value;
}
}
let s1 = new Student();
console.log(s1.firstName);
s1.firstName = 'xiaohei';
console.log(s1.firstName);
3、通过Object.defineProperty()定义getter和setter
不了解
Object.defineProperty()
使用方法的同学可以阅读:属性描述对象 - JavaScript 教程 - 网道
取值函数get不能接受参数,存值函数set只能接受一个参数(即属性的值)。
案例1:
var obj = Object.defineProperty({}, 'p', {
get: function () {
return 'getter';
},
set: function (value) {
console.log('setter: ' + value);
}
});
obj.p // "getter"
obj.p = 123 // "setter: 123"
案例2:
function Animal() {
let _age = 2; // 可以实现私有属性
Object.defineProperty(this,'age',{
get:function () {
console.log('get age');
return _age;
},
set:function (value) {
console.log('set age');
_age = value;
}
})
}
let dog = new Animal();
console.log(dog.age);
dog.age = 4;
console.log(dog.age);
4、小结
如果一个属性具有getter和setter方法,访问该属性时将隐式调用getter方法,为该属性赋值时将隐式调用setter方法。
针对指定的属性不一定需要同时定义 getter和 setter。例如,通常我们可以仅提供 getter。如果在这种情况下试图写入属性值,具体的行为取决于代码是在严格模式还是非严格模式。如果在非严格模式下,对仅有getter 的属性赋值不起作用,JavaScript引擎默默地忽略我们的请求。另一方面,如果在严格模式下,JavaScript引擎将会抛出异常,表明我们试图将给一个仅有 getter没有setter的属性赋值。
二、使用代理控制对象的访问
可以看我写的另一篇博客:JS中代理Proxy的简单使用