对象属性的get和set详解

你可能见过类似下面的代码:

const r = {
    get value() {
        return value
    },
    set value(newValue) {
        if (newValue !== this.value) {
            this.value = newValue
        }
    }
}

这里的get和set写法是什么意思?为啥对象属性可以这样设置,不应该是xx:xxx的写法吗?

在传统的javaScript中,对象属性可以通过两种方式设置:

  • 点表示法:objectName.propertyName
  • 方括号表示法:objectName['propertyName']

但有时需要允许访问返回动态计算值的属性,或者需要反映内部变量的状态,而需要使用显式方法调用。因而在ES5 引入了getset,允许开发者定义getter setter 方法,以便更灵活地控制属性的访问和赋值过程。

get(getter)

get 语法将对象属性绑定到查询该属性时将被调用的函数,简称获取对象属性的时候调用绑定的函数。

语法

创建

{get prop() { ... } }
{get [expression]() { ... } }

参数说明:

  • prop 要绑定到给定函数的属性名,即对哪个属性名进行监听
  • expression 使用一个计算属性名的表达式绑定到给定的函数。

注意事项:

  • 必须不带参数

  • 不能另一个 get 或具有相同属性的数据条目同时出现在一个对象字面量中(不允许使用 { get x() { }, get x() { } }{ x: ..., get x() { } })。

删除

删除使用delete,就可删除getter

实例

// {get prop() { ... } }
const obj = {
  log: ["example", "test"],
  get latest() {
    if (this.log.length == 0) return undefined;
    return this.log[this.log.length - 1];
  },
};
console.log(obj.latest); // "test".
// {get [expression]() { ... } } 使用计算出的属性名
var expr = "foo";
var obj = {
  get [expr]() {
    return "bar";
  },
};
console.log(obj.foo); // "bar"
// 删除
delete obj.latest;

get VS defineProperty

当使用 get 关键字时,它和Object.defineProperty() 有类似的效果。而在类中使用时,get会将**getter** 方法定义类的原型上;Object.defineProperty() 可以选择将属性定义在对象的实例上,可以将其定义在原型上。

在类中使用 get 关键字的效果类似于在类的原型上使用 Object.defineProperty() 来定义属性的 getter 方法,而不是直接定义属性。

这意味着当你创建类的实例时,这个 getter 方法将在实例的原型链上被继承,而不是实例本身上。

class Example {
  get hello() {
    return "world";
  }
}
const obj = new Example();
const obj2 = new Example();
// get 关键字定义在类的原型上,因此所有 MyClass 的实例都共享相同的 getter 方法。
console.log(obj.hello);// "world"
console.log(obj2.hello); // "world" 
console.log(Object.getOwnPropertyDescriptor(obj, "hello")); // undefined

Object.getOwnPropertyDescriptor():静态方法返回一个对象,该对象描述给定对象上特定属性(即直接存于对象上而不在对象的原型链中的属性)的配置。

// 使用 Object.defineProperty() 定义属性

// 未指定 obj 的原型,因此该属性只存在于 obj 自身上。
const obj = {};
Object.defineProperty(obj3, 'value', {
    get: function() {
        return 'getter';
    }
});
console.log(obj3.value); // 输出 'getter'
// 显式地将属性定义在对象的原型上
function MyClass() {}
Object.defineProperty(MyClass.prototype, 'value', {
    get: function() {
        return 'getter';
    }
     set: function(newValue) {
        this._value = newValue;
    },
    enumerable: true,
    configurable: true
});
const obj = new MyClass();
console.log(obj.value); // 输出 'getter'
  • enumerable

    • true 时,该属性可以在对象的枚举属性中被枚举到(默认情况为true)。
    • false,则该属性将不会出现在枚举中,例如在 for...in 循环中或通过 Object.keys() 方法获取对象的键时不会包含该属性。
  • configurable

    • true 时,该属性可以被删除属性的特性也可以被修改
    • false,则该属性不能被删除,属性的特性也不能再次修改,且无法再将其改为 true
    • 默认情况是 false:为了保护对象的一致性和完整性,防止意外修改或删除重要属性

set(setter)

set 语法将对象属性绑定到要调用的函数,简称修改属性值的时候调用绑定的函数

语法

创建

{ set prop(val) { /* … */ } }
{ set [expression](val) { /* … */ } }

参数说明:

  • prop 要绑定到给定函数的属性名,即对哪个属性名进行监听
  • val 保存尝试分配给**prop的值**的变量的一个别名
  • expression 使用一个计算属性名的表达式绑定到给定的函数。

注意事项:

  • 必须有一个明确的参数

  • 在对象字面量中,不能为一个已有真实值的变量使用 set,也不能为一个属性设置多个 set。 ( { set x(v) { }, set x(v) { } }{ x: ..., set x(v) { } } 是不允许的 )。

删除

删除使用delete,就可删除setter

实例

// { set prop(val) { /* … */ } }
const language = {
  set current(name) {
    this.log.push(name);
  },
  log: [],
};
language.current = "EN";
console.log(language.log); // ['EN']
language.current = "FA";
console.log(language.log); // ['EN', 'FA']

// { set [expression](val) { /* … */ } }
const expr = "foo";
const obj = {
  baz: "bar",
  set [expr](v) {
    this.baz = v;
  },
};
console.log(obj.baz); // "bar"
obj.foo = "baz"; // run the setter
console.log(obj.baz); // "baz"

// 删除
delete language.current;

getterhttps://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/get

setterhttps://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/set

  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
计算属性是指通过一些逻辑计算而来的属性,它们的值并不是在对象实例化时就确定的,而是在访问时根据计算规则动态获取的。在 JavaScript ,我们可以使用 get 和 set 关键字来定义计算属性。 get 关键字用于定义计算属性的读取方法,当访问该属性时,会自动调用 get 方法并返回计算后的值。set 关键字用于定义计算属性的设置方法,当给该属性赋值时,会自动调用 set 方法,并根据传入的值进行计算和赋值。 下面是一个例子,展示了如何使用 get 和 set 关键字定义一个计算属性: ``` const obj = { _value: 0, get value() { console.log('Getting value...'); return this._value; }, set value(newValue) { console.log('Setting value...'); this._value = newValue * 2; } }; console.log(obj.value); // 输出 "Getting value... 0" obj.value = 10; // 输出 "Setting value..." console.log(obj.value); // 输出 "Getting value... 20" ``` 在上面的例子,我们定义了一个名为 value 的计算属性,它的实际值存储在 obj._value 。当我们访问 obj.value 时,会自动调用 get 方法并输出 "Getting value...",然后返回 obj._value 的值。当我们给 obj.value 赋值时,会自动调用 set 方法并输出 "Setting value...",然后计算 newValue * 2 并将结果赋值给 obj._value。最后,再次访问 obj.value 时,会自动调用 get 方法并输出 "Getting value...",然后返回计算后的值 20。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值