📄
fe-share
  • fe-share
  • JavaScript
    • Canvas 图片处理
    • Javascript 性能
    • JavaScript 原型(2) - 原型与原型链
    • JavaScript 原型(1) - 构造函数
    • JavaScript - Promise
    • Canvas 灰度
    • ES6 解构赋值
    • Proxy
    • Object.defineProperty()简介
  • Engineering
    • 登录鉴权
    • 缓存
    • Chrome-devtools
    • Docker
    • 技术架构演化
    • Git
    • webpack
    • BS 架构与 CS 架构
    • SVN(Subversion)
    • gulp
    • 前端架构
  • MachineLearning
    • GAN生成对抗网络
    • 虚拟对抗训练
    • 深度度量学习
    • 原型网络
    • 联邦学习
    • 机器学习常见评价指标
    • Transformer算法
    • Self-attention 推荐算法
    • CNN 卷积神经网络
    • 集成学习算法
    • RNN循环神经网络
    • PyTorch安装和基本操作
  • CSS
    • 什么是BFC
  • React
    • React 生命周期
    • Hooks
    • SWR
    • React 数据流
  • 跨端
    • Flutter 介绍
  • Golang
    • Golang 基础
  • Vue
    • nextTick()的使用
    • vue-cli2.x 的使用与项目结构分析
    • Vue响应式原理及总结
    • VueX的使用
    • 记录一个问题的探索过程
  • Node
    • Node 优势
    • Node Stream
    • Node 模块系统
  • AR
    • SceneKit
由 GitBook 提供支持
在本页
  • 1. 定义
  • 2. 语法
  • 3. 属性描述符
  • 4. 属性描述符的键值
  • 数据描述符独有的两个键值(value, writable)
  • 存取描述符独有的两个键值(get, set)
  • 混合使用两种描述符的键值
  • 数据描述符和存取描述符共同具有的键值(configurable, enumerable)

这有帮助吗?

  1. JavaScript

Object.defineProperty()简介

Object.defineProperty() 是一个定义在 Object 构造函数上的方法。从命名就可以看出,此方法用于定义对象的属性。Vue 中就是使用此方法完成数据劫持,并实现双向绑定的。通过对此方法的学习,也为之后熟悉 Vue 双向绑定做准备。

1. 定义

  • 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。

2. 语法

Object.defineProperty(obj, prop, descriptor);
  • obj : 要在其上定义属性的对象

  • prop : 要定义或修改的属性的名称

  • descriptor : 将被定义或修改的属性描述符

  • 返回值 : 被传递给函数的对象

3. 属性描述符

  • 对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。

  • 数据描述符是一个具有值的属性,该值可能是可写的,也可能不是可写的。

  • 存取描述符是由 getter-setter 函数对描述的属性。

  • 属性描述符只能同时为两个形式中的一个。

4. 属性描述符的键值

把属性本身想象为一个对象,键值参数其实就用于描述该对象的属性。键值共有六个,具有以下表格中的特性。

属性名

value

get

set

writable

enumerable

configurable

默认值

undefined

undefined

undefined

false

false

false

数据描述符

Yes

No

No

Yes

Yes

Yes

存取描述符

No

Yes

Yes

No

Yes

Yes

数据描述符独有的两个键值(value, writable)

  • value : 用于定义属性的值。

  • writable : 用于描述属性是否可写。

一个很简单的应用 :

let coder = {};
Object.defineProperty(coder, "lang", {
  value: "JavaScript",
  writable: true,
});
console.log(coder.lang); // "JavaScript"

// writable为true时,对象的属性可写
coder.lang = "Java";
console.log(coder.lang); // "Java"

当然,当我们不添加 writable 属性时,属性的值将不可修改(默认为 false)

let coder = {};
Object.defineProperty(coder, "lang", {
  value: "JavaScript",
});
console.log(coder.lang); // "JavaScript"

// writable为默认值时,对象的属性不可写
coder.lang = "Java";
console.log(coder.lang); // "JavaScript"

存取描述符独有的两个键值(get, set)

  • get : 一个给属性提供获取值的方法,该方法返回值被用作属性值。无默认值则返回 undefined。

  • set : 一个给属性提供设置值的方法。该方法将接受唯一参数,并将该参数的新值分配给该属性。

let coder = {};
let tmp = "JavaScript";
Object.defineProperty(coder, "lang", {
  value: "JavaScript",
  writable: true,
  get: () => {
    return tmp;
  },
  set: (val) => {
    tmp = val;
  },
});
// 直接获取对象属性值
console.log(coder.lang); // "JavaScript"

// 设置对象属性值后再次获取
coder.lang = "Java";
console.log(coder.lang); // "Java"

混合使用两种描述符的键值

当上述两类特有的键值被一起使用时,就违反了描述符本身的定义,出现语法错误。

数据描述符和存取描述符共同具有的键值(configurable, enumerable)

  • configrable : 描述属性是否配置,以及可否删除。

  • enumerable : 描述属性是否会出现在 for in 或者 Object.keys()的遍历中。

先对configurable进行分析

let coder = {};
Object.defineProperty(coder, "lang", {
  value: "JavaScript",
  writable: true,
  configurable: false,
  enumerable: true,
});
// 首先,configurable为false时,属性不可删除
delete coder.lang;
console.log(coder.lang); // "JavaScript"

// 但如果writable为true可以通过赋值修改内容
coder.lang = "Java";
console.log(coder.lang); // "Java"

// 通过配置方法直接改值则会报错
Object.defineProperty(coder, "lang", {
  value: "JavaScript",
});
// Uncaught TypeError: Cannot redefine property: lang

有个神奇的特殊情况是,configurable 为 false 时,writable 的值可以从 true 改为 false,反之则不行。

再分析enumerable,可以发现与其定义完全符合。

let coder = {};
coder.lang = "JavaScript";
Object.defineProperty(coder, "frame", {
  value: "Vue",
  enumerable: false,
});
Object.defineProperty(coder, "work", {
  value: "996",
  enumerable: true,
});

// 通过for in与Object.keys()方法遍历对象
for (let key in coder) {
  console.log(key);
}
// "lang"  "work"
console.log(Object.keys(coder)); // ["lang", "work"]

在以上的使用中,我们又可以发现一个特殊的用法,即直接给对象属性赋值。

  • 当调用 Object.defineProperty()配置属性时,没有赋值的数据描述符取默认值。

  • 当直接对属性赋值时,如以上代码块第二行,则value以外的数据描述符均为 true。

上一页Proxy下一页Engineering

最后更新于4年前

这有帮助吗?

数据描述符与存取描述符共存