LOGO 首页 OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 技术文档 其他文档  
 
网站管理员

为什么要有访问器? 你不知道的对象属性

zhenglin
2026年10月10日 15:16 本文热度 191

在 JavaScript 里,对象的属性其实分为两种截然不同的“物种”:数据属性(Data Property)  和 访问器属性(Accessor Property) 。

1.什么是数据属性?(你平时写的那个)

当你写:

class User {

    username: string;

}

或者

const obj = { username: '' };

JS 引擎在底层把 username 定义为一个数据属性(Data Property) 。

  • 数据属性里有一个叫 value 的字段,直接存着 ''。


  • 你写 obj.username = 'Alice',引擎是直接去修改那个 value 字段。没有函数参与,没有拦截,简单粗暴,也不需要 get/set。


2. 什么是访问器属性?

访问器属性根本不存值。它是一个自动售货机。
你没有储物柜,只有两个按钮:一个叫 get(取货),一个叫 set(存货)。

当你读这个属性时,引擎发现它是个访问器属性,就会去按 get 按钮,执行你写的 getter 函数。
当你写这个属性时,引擎就会去按 set 按钮,执行你写的 setter 函数。

例子(字面量写法):

javascript

const user = {

    _name: 'Alice', // 这是个真正存值的普通属性


    get name() {

        console.log('正在读取 name');

        return this._name;

    },


    set name(newVal) {

        console.log('正在修改 name');

        this._name = newVal;

    }

};


user.name;          // 触发 get,打印:正在读取 name

user.name = 'Bob';  // 触发 set,打印:正在修改 name

这里的 name 就是一个访问器属性,它本身没有值,值存在 _name 里。

3. 核心区别

特征数据属性 (Data Property)访问器属性 (Accessor Property)
本质储物柜自动售货机
是否有 value有,直接存值没有,值由外部或闭包保存
是否有 get/set没有有,读写全由函数接管
读写行为直接读/写内存里的值触发函数调用,执行代码逻辑
能否自定义行为不能,赋值就是纯粹赋值能,可以在读/写时做任何事(校验、日志、计算)

4. 为什么要有访问器属性?它有什么用?

它赋予了开发者 “拦截并控制属性读写” 的超能力。比如:

场景 A:数据校验(防瞎填)

javascript

const person = {

    _age: 0,

    set age(val) {

        if (val < 0 || val > 150) {

            throw new Error('年龄不合法!');

        }

        this._age = val;

    },

    get age() {

        return this._age;

    }

};

person.age = -5; // 报错:年龄不合法!

场景 B:计算属性(互相依赖)

javascript

const rect = {

    width: 10,

    height: 20,

    get area() {

        return this.width * this.height; // 每次读取,动态计算

    }

};

console.log(rect.area); // 200

area 并不存值,它是通过 width 和 height 实时算出来的。

5. 为什么访问器属性自己没地方存值?

要理解这个,我们要回到 JS 引擎的底层设计。在 JS 中,属性描述符(Property Descriptor)是有固定形状(Shape) 的,它严格分为两套互相排斥的配置:

  • 数据属性的配置:{ value, writable, enumerable, configurable }

  • 访问器属性的配置:{ get, set, enumerable, configurable }

JS 引擎有一条铁律:绝对不允许同时出现 value 和 get/set。

如果你强行在 Object.defineProperty 里同时写:

javascript

Object.defineProperty(target, 'username', {

    value: '游客', // 试图存值

    get() { return 'Alice'; } // 试图拦截

});

// 引擎会直接抛出 TypeError,报错说:Invalid property descriptor. Cannot both specify accessors and a value or writable attribute.

为什么引擎要这么设计?(结合比喻)

  • 数据属性就像一个储物柜。引擎分配了一块内存存 value。

  • 访问器属性就像一个自动售货机。它只提供了 get(出货按钮)和 set(进货按钮)。

如果你把属性定义成了访问器属性(安装上了按钮),引擎就会在底层把这个属性标记为“访问器”。
此时,它不再分配用来存 value 的内存槽位。
如果强行赋值 u2.username = 'Alice',引擎只会去按 set 按钮。如果没写 set,引擎既没按钮可按,又没 value 可改,只能报错。

所以,不是它“没地方存”,而是 JS 引擎在底层强行把它的“存储槽位”砍掉了,逼迫你必须自己找地方存。  最常见的地方就是闭包变量或者WeakMap。


阅读原文:点击这里​


该文章在 2026/10/10 15:16:09 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved  粤ICP备13012886号-9  粤公网安备44030602007207号