Rodrick

vuePress-theme-reco Rodrick    2022
Rodrick Rodrick

Choose mode

  • dark
  • auto
  • light
Home
Category
  • CS基础
  • 数据库
  • 前端
  • 其他
Tag
About
Timeline
D&T
  • 官方文档

    • Vue
    • Vue3
    • Webpack
    • MDN
    • Node中文网
    • React
    • 小程序
    • FineReport
  • 学习面试

    • 现代JavaScript教程
    • ES6
    • 阿西河
    • LeetCode
    • 牛客网
  • 工具

    • bejson
Contact
  • Github
  • Gitee
author-avatar

Rodrick

62

Article

18

Tag

Home
Category
  • CS基础
  • 数据库
  • 前端
  • 其他
Tag
About
Timeline
D&T
  • 官方文档

    • Vue
    • Vue3
    • Webpack
    • MDN
    • Node中文网
    • React
    • 小程序
    • FineReport
  • 学习面试

    • 现代JavaScript教程
    • ES6
    • 阿西河
    • LeetCode
    • 牛客网
  • 工具

    • bejson
Contact
  • Github
  • Gitee
  • JS

    • ES6核心语法
    • 模块化&Webpack
    • Promise&异步函数async
    • WebSocket原理浅析
    • axios的使用
    • ES5的变量提升和ES6的暂时性死区
    • call、apply、bind的用法
    • 对象的原始值转换
    • 可选链"?."
    • 随机数方法
    • 深浅拷贝实现
    • Array常用处理
    • 防抖与节流
    • postMessage窗口间通讯
    • 解构赋值
    • Map&Set
    • 日期和时间
    • 对象属性
    • Toast组件简单封装
    • 原型链
    • 类 Class
    • Generator与异步迭代
    • 偏函数Partial和柯里化Currying
    • DOM操作
    • 事件处理
    • 事件循环EventLoop
    • 网络请求
    • 浏览器中存储数据
    • 正则表达式
  • CSS

  • 其他

对象属性

vuePress-theme-reco Rodrick    2022

对象属性

Rodrick 2020-11-27 js

# 属性标志和属性描述符

# 对象属性

对象属性(properties),除 value 外,还有三个特殊的特性(attributes),也就是所谓的“标志”:

  • writable — 如果为 true,则值可以被修改,否则它是只可读的。
let user = {
  name: "John"
};

Object.defineProperty(user, "name", {
  writable: false
});
/* 只会在 user strict 时会报错,一般情况下不报错但是修改会无效 */
user.name = "Pete"; // Error: Cannot assign to read only property 'name'
  • enumerable — 如果为 true,则会被在循环中列出,否则不会被列出。
let user = {
  name: "John",
  toString() {
    return this.name;
  }
};

Object.defineProperty(user, "toString", {
  enumerable: false
});

// 现在我们的 toString 消失了:
for (let key in user) alert(key); // name
  • configurable — 如果为 true,则此特性可以被删除,这些属性也可以被修改,否则不可以。用途是防止更改和删除属性标志,但是允许更改对象的值。如果他和 writable 都是 false ,那么这个值永远不可修改了。
let user = {
  name: "John"
};

Object.defineProperty(user, "name", {
  configurable: false
});

user.name = "Pete"; // 正常工作
delete user.name; // Error

# 获取对象属性

  • Object.getOwnPropertyDescriptor  方法允许查询有关属性的 完整 信息
let descriptor = Object.getOwnPropertyDescriptor(obj, propertyName);
  • obj需要从中获取信息的对象。
  • propertyName属性的名称。
  • 返回值是一个所谓的“属性描述符”对象:它包含值和所有的标志。
let user = {
  name: "John"
};

let descriptor = Object.getOwnPropertyDescriptor(user, 'name');

alert( JSON.stringify(descriptor, null, 2 ) );
/* 属性描述符:
{
  "value": "John",
  "writable": true,
  "enumerable": true,
  "configurable": true
}
*/
  • 要一次获取所有属性描述符,我们可以使用 Object.getOwnPropertyDescriptors(obj)  方法。

它与 Object.defineProperties 一起可以用作克隆对象的“标志感知”方式,如果需要克隆一个对象并且要连带属性标志一起克隆的话,一般的克隆方式是不行的,这时候我们可以:

// Object.getOwnPropertyDescriptors 返回包含 symbol 类型的属性在内的 所有 属性描述符。
let clone = Object.defineProperties({}, Object.getOwnPropertyDescriptors(obj));

# 修改对象属性

  • Object.defineProperty 修改单个属性
Object.defineProperty(user, "name", {
  value: "John"
});
  • Object.defineProperties(obj, descriptors) 批量修改属性
Object.defineProperties(user, {
  name: { value: "John", writable: false },
  surname: { value: "Smith", writable: false },
  // ...
});

# 对整个对象进行限制

属性描述符在单个属性的级别上工作。
还有一些限制访问 整个 对象的方法:

  • Object.preventExtensions(obj) 禁止向对象添加新属性。
  • Object.seal(obj) 禁止添加/删除属性。为所有现有的属性设置 configurable: false。
  • Object.freeze(obj) 禁止添加/删除/更改属性。为所有现有的属性设置 configurable: false, writable: false。


还有针对它们的测试:

  • Object.isExtensible(obj) 如果添加属性被禁止,则返回 false,否则返回 true。
  • Object.isSealed(obj) 如果添加/删除属性被禁止,并且所有现有的属性都具有 configurable: false则返回 true。
  • Object.isFrozen(obj) 如果添加/删除/更改属性被禁止,并且所有当前属性都是 configurable: false, writable: false,则返回 true。

# 访问器属性 getter/setter

# Getter 和 setter

  • 用法:
let user = {
  name: "John",
  surname: "Smith",

  get fullName() {
    return `${this.name} ${this.surname}`;
  },

  set fullName(value) {
    [this.name, this.surname] = value.split(" ");
  }
};

// set fullName 将以给定值执行
user.fullName = "Alice Cooper";

alert(user.name); // Alice
alert(user.surname); // Cooper

# 访问器描述符

访问器属性的描述符与数据属性的不同。
对于访问器属性,没有 value 和 writable,但是有 get 和 set 函数。
所以访问器描述符可能有:

  • get —— 一个没有参数的函数,在读取属性时工作,
  • set —— 带有一个参数的函数,当属性被设置时调用,
  • enumerable —— 与数据属性的相同,
  • configurable —— 与数据属性的相同。
let user = {
  name: "John",
  surname: "Smith"
};

Object.defineProperty(user, 'fullName', {
  get() {
    return `${this.name} ${this.surname}`;
  },

  set(value) {
    [this.name, this.surname] = value.split(" ");
  }
});

alert(user.fullName); // John Smith

for(let key in user) alert(key); // name, surname

请注意,一个属性要么是访问器(具有 get/set 方法),要么是数据属性(具有 value),但不能两者都是。
如果我们试图在同一个描述符中同时提供 get 和 value,则会出现错误

// Error: Invalid property descriptor.
Object.defineProperty({}, 'prop', {
  get() {
    return 1
  },

  value: 2
});
欢迎来到 Rodrick
看板娘