为了账号安全,请及时绑定邮箱和手机立即绑定

原型中的 Setter 属性与数据属性

原型中的 Setter 属性与数据属性

POPMUISE 2023-07-29 14:51:56
有人可以解释以下行为吗?var p = {  name: "John",  set age(value) {    console.log("Age set to", value);  }}var obj = {};Object.setPrototypeOf(obj, p);obj.name = "Jill"; // Doesn't alter the name on prototype, creates a new property on objobj.age = 22; // Calls the setter on prototype为什么分配 to 会age调用原型上的 setter,而分配 toname会在 上创建新属性obj?
查看完整描述

2 回答

?
凤凰求蛊

TA贡献1825条经验 获得超4个赞

这就是 JavaScript 的工作原理。当=用于分配属性时,引擎将在对象的原型链中查找第一个与属性名称匹配的属性描述符。如果找到这样的描述符,并且该描述符是访问器(即,具有 setter 和/或 getter),则将调用该 setter。否则,如果描述符是数据描述符,则没有 setter,新值将分配给实例自己的属性。

  1. 断言:IsPropertyKey(P) 为 true。

  2. 如果 ownDesc 未定义,则

    1. 将 ownDesc 设置为 PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }。

    2. 返回 ?父级。[[设置]](P、V、接收器)。这就是递归调用。`ownDesc` 设置为包含此属性名称的描述符的第一个祖先。

    3. 让父母成为?O.[[GetPrototypeOf]]()。

    4. 如果父级不为空,则

    5. 别的,

  3. 如果 IsDataDescriptor(ownDesc) 为 true,则

    1. 断言:接收者当前没有属性 P。

    2. 返回 ?CreateDataProperty(接收器,P,V)。

    3. 如果 IsAccessorDescriptor(existingDescriptor) 为 true,则返回 false。

    4. 如果existingDescriptor.[[Writable]]为假,则返回假。

    5. 令 valueDesc 为 PropertyDescriptor { [[Value]]: V }。

    6. 返回 ?接收者。[[DefineOwnProperty]](P, valueDesc)。使用数据描述符,实例(即“接收器”)会获取分配给它的新值,无论描述符在原型链中的哪个位置找到。

    7. 如果 ownDesc.[[Writable]] 为 false,则返回 false。

    8. 如果 Type(Receiver) 不是 Object,则返回 false。

    9. 让现有描述符是?接收者。[[GetOwnProperty]](P)。

    10. 如果existingDescriptor不是未定义的,那么

    11. 别的,

  4. 断言:IsAccessorDescriptor(ownDesc) 为 true。

  5. 设 setter 为 ownDesc.[[Set]]。

  6. 如果 setter 未定义,则返回 false。

  7. 履行 ?呼叫(二发手、接发手、“V”)。否则,调用 setter。

  8. 返回真。


查看完整回答
反对 回复 2023-07-29
?
人到中年有点甜

TA贡献1895条经验 获得超7个赞

当您分配给属性时,它首先在原型链中搜索 setter。如果找到 setter,则简单地执行它。

如果没有找到 setter,则会在对象本身中创建或更新普通属性。分配属性永远不会单独分配给继承的属性(setter 可以这样做)。


查看完整回答
反对 回复 2023-07-29
  • 2 回答
  • 0 关注
  • 84 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信