js中的Object.defineProperty()详解

news2025/1/15 10:33:27

文章目录

  • 一、Object.defineProperty()
  • 二、descriptor属性描述符
    • 2.1、数据描述符
    • 2.2、访问器描述符
    • 2.3、descriptor属性
      • 2.3.1、value
      • 2.3.2、writable
      • 2.3.3、enumerable (可遍历性)
      • 2.3.4、configurable (可配置性)
  • 三、注意事项

一、Object.defineProperty()

Object.defineProperty() 方法允许精确地添加或修改对象的属性,并返回此对象。默认情况下,使用此方法添加的属性是不可修改的。

基本语法

Object.defineProperty(obj, prop, descriptor)

参数说明:

  • obj: 要定义属性的对象
  • prop: 要定义或修改的属性名
  • descriptor: 属性描述符对象

descriptor 对象包含以下属性:

  • value:属性的值,默认为undefined
  • writable:属性的可写性。默认为false,即该属性为只读属性。
  • enumerable:属性的可枚举性。默认为false,即该属性不可枚举。
  • configurable:属性的可配置性。默认为false,即该属性不可被删除。
  • get:获取属性值的函数。
  • set:设置属性值的函数。

返回值

  • 传入函数的对象,其指定的属性已被添加或修改。

二、descriptor属性描述符

对象中存在的属性描述符有两种主要类型:数据描述符访问器描述符

  • 数据描述符是一个具有可写或不可写值的属性。
  • 访问器描述符是由 getter/setter 函数对描述的属性。

描述符只能是这两种类型之一,不能同时为两者
在这里插入图片描述

2.1、数据描述符

const obj = {};

Object.defineProperty(obj, 'name', {
  value: 'John',          // 属性值
  writable: true,         // 是否可写
  enumerable: true,       // 是否可枚举
  configurable: true      // 是否可配置
});

html代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script type="text/javascript">
        const obj = {};

        Object.defineProperty(obj, 'name', {
            value: 'John',          // 属性值
            writable: true,         // 是否可写
            enumerable: true,       // 是否可枚举
            configurable: true      // 是否可配置
        });
        console.log(obj)
    </script>
    
</body>
</html>

运行后控制台输出:
在这里插入图片描述

2.2、访问器描述符

const obj = {
  _name: 'John'
};

Object.defineProperty(obj, 'name', {
  get() {
    return this._name;
  },
  set(value) {
    this._name = value;
  },
  enumerable: true,
  configurable: true
});

2.3、descriptor属性

2.3.1、value

value: 属性的值,可以是任何有效的 JavaScript 值(数值,对象,函数等),不设置的话默认为 undefined

let person = {
    name: "张三",
    sex: "男",
  };
  Object.defineProperty(person, 'age', {
      value: 18,
  })
 
console.log(person); // {name: '张三', sex: '男', age: 18}
person.age=20;  //设置更改年龄,但是发现更改失败,因为writable属性默认为false
console.log(person);

2.3.2、writable

writable 是一个布尔值,决定了目标属性的值(value)是否可以被改变。

● writable默认为false, 当 writable 设置为 false 时,使用 赋值运算符 修改属性的值,不会报错,但也不会生效。

let person = {
  name: "张三",
  sex: "男",
};
Object.defineProperty(person, 'age', {
   value: 18,
})
 
console.log(person); // {name: '张三', sex: '男', age: 18}
person.age=20;  //设置更改年龄,但是发现更改失败,因为writable属性默认为false
console.log(person);// {name: '张三', sex: '男', age: 18}  输出后还是18

● 当 writable 设置为 false 时,使用 Object.defineProperty() 修改属性的值,会直接报错。

let person = {
  name: "张三",
  sex: "男",
};
Object.defineProperty(person, 'age', {
   value: 18,
   writable:true
})
 
console.log(person); // {name: '张三', sex: '男', age: 18}

Object.defineProperty(person, 'age', {
   value: 20
}) //抛错 Uncaught SyntaxError: Identifier 'person' has already been declared

console.log(person);

● writable设置为true,使用 赋值运算符或者 Object.defineProperty() 都可以修改属性的值。

let person = {
    name: "张三",
    sex: "男",
};
Object.defineProperty(person, 'age', {
    value: 18,
    writable:true
})

console.log(person); // {name: '张三', sex: '男', age: 18}
person.age=20;  //设置更改年龄
console.log(person); // {name: '张三', sex: '男', age: 20}

Object.defineProperty(person, 'age', {
    value: 21
})
console.log(person); // {name: '张三', sex: '男', age: 21}

2.3.3、enumerable (可遍历性)

enumerable 是一个布尔值,表示目标属性在 for…in、Object.keys、JSON.stringify 中是否可遍历。

● 当 enumerable 设置为 true 时,目标属性可被遍历操作。

let person = {
    name: "张三",
    sex: "男",
};
Object.defineProperty(person, 'age', {
    value: 18,
    enumerable:true
})

for (const key in person) {
  console.log(' for in', key);
}
console.log('Object.keys:', Object.keys(person));
console.log('JSON.stringify:', JSON.stringify(person));

在这里插入图片描述
● 当 enumerable 设置为 false 时,目标属性不可被遍历操作。

let person = {
    name: "张三",
    sex: "男",
};
Object.defineProperty(person, 'age', {
    value: 18,
    enumerable:false
})

for (const key in person) {
  console.log(' for in', key);  //只输出name, sex,不会输出age
}
console.log('Object.keys:', Object.keys(person));
console.log('JSON.stringify:', JSON.stringify(person));

在这里插入图片描述
● for…in 循环包括继承的属性,Object.keys 方法不包括继承的属性。如果需要获取对象自身的所有属性,不管是否可遍历,可以使用 Object.getOwnPropertyNames 方法。

2.3.4、configurable (可配置性)

configurable 是一个布尔值,决定了是否可以修改 属性描述对象 以及表示能否通过 delete 删除属性。

● 当 configurable 为 false 时,不能否通过 delete 删除属性。

// 定义对象
const myObject = {};
// 设置 configurable 为 false
Object.defineProperty(myObject, 'firstName', {
value: 'first',
configurable: false,
});
// 设置 configurable 为 true
Object.defineProperty(myObject, 'lastName', {
value: 'last',
configurable: true,
});
console.log('before delete ~ myObject.firstName :', myObject.firstName);
console.log('before delete ~ myObject.lastName :', myObject.lastName);
delete myObject.firstName
delete myObject.lastName
console.log('after delete ~ myObject.firstName :', myObject.firstName);
console.log('after delete ~ myObject.lastName :', myObject.lastName);

在这里插入图片描述

可以看到 configurable 为 false 时,delete 属性不会报错,但也不会生效。

可以看到 configurable 为 true 时,delete 属性会生效,属性变为 undefined。

● 当 configurabletrue 并且 writabletrue 时,通过 赋值运算符 修改 value 的修改才会生效。

// 定义对象
const myObject = {};
// 设置 configurable 为 true,writable 默认为 false
Object.defineProperty(myObject, 'firstName', {
  value: 'han',
  configurable: true,
});
// 设置 configurable 为 true,writable 为 true
Object.defineProperty(myObject, 'lastName', {
  value: 'zhiwei',
  configurable: true,
  writable: true,
});
console.log('before change ~ myObject.firstName :', myObject.firstName); //han
myObject.firstName = 'zhang'
console.log('after change ~ myObject.firstName :', myObject.firstName); //han 没有生效

console.log('before change ~ myObject.lastName :', myObject.lastName); //zhiwei
myObject.lastName = 'san'
console.log('after change ~ myObject.lastName :', myObject.lastName); //san 生效了

● 当 configurable 何 writable 其中有任意一个为 true 时,通过 Object.defineProperty() 方法修改属性的值,就会生效。

// 定义对象
const myObject = {};
// 设置 configurable 为 true,writable 为 false
Object.defineProperty(myObject, 'firstName', {
  value: 'han',
  configurable: true,
  writable: false
});
Object.defineProperty(myObject, 'firstName', {
  value: 'wang',
});
console.log('myObject.firstName:', myObject.firstName); // wang
// 定义对象
const myObject = {};
// 设置 configurable 为 false,writable 为 true
Object.defineProperty(myObject, 'firstName', {
  value: 'han',
  configurable: false,
  writable: true
});
Object.defineProperty(myObject, 'firstName', {
  value: 'wang',
});
console.log('myObject.firstName:', myObject.firstName); // wang

● 当 configurable 为 false 时, enumerable, configurable 都不可修改,会直接报错。

// 定义对象
const myObject = {};
// 设置 enumerable 为 trueObject.defineProperty(myObject, 'firstName', {
  value: 'han',
  configurable: false,
  enumerable: true,
});
// 设置 enumerable 为 falseObject.defineProperty(myObject, 'firstName', {
  value: 'wang',
  configurable: false,
  enumerable: false,
});
console.log('Descriptor:', Object.getOwnPropertyDescriptor(myObject, 'firstName'));

● 当 configurable 为 false 时, writable 可以由 true 改为 false ,但不可由 false 改为 true ,否则会报错。

// 定义对象
const myObject = {};
// 设置 writable 为 trueObject.defineProperty(myObject, 'firstName', {
  value: 'han',
  configurable: false,
  writable: true
});
// 设置 writable 为 falseObject.defineProperty(myObject, 'firstName', {
  value: 'wang',
  configurable: false,
  writable: false,
});
console.log('Descriptor:', Object.getOwnPropertyDescriptor(myObject, 'firstName'));

● 当 configurable 为 false 时, getter 和 setter 方法无法被修改。

// 定义对象 
const myObject = {};
Object.defineProperty(myObject, 'firstName', {
  configurable: false,
  get() {
    console.log('读取了 myObject.firstName:');
    return this.value;
  },
  set(newValue) {
    console.log('修改了 myObject.firstName:');
    this.value = newValue;
  },
});
Object.defineProperty(myObject, 'firstName', {
  configurable: false,
  get() {
    console.log('读取了 myObject.firstName:');
    return this.value + 'y';
  },
  set(newValue) {
    console.log('修改了 myObject.firstName:');
    this.value = newValue + 'y';
  },
});

三、注意事项

注意事项:
Object.defineProperty() 设置了getter和setter方法之后,就不能再设置value属性,否则控制台报错:Uncaught TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object>



参考或推荐文档:
1.Object.defineProperty
2.https://www.jb51.net/javascript/3335118jy.htm
3.https://blog.51cto.com/u_12379999/13028626

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2276957.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

单细胞组学大模型(8)--- scGenePT,scGPT和GenePT的结合,实验数据和文本数据的交融模型

–https://doi.org/10.1101/2024.10.23.619972 研究团队和单位 Theofanis Karaletsos–Head Of AI - Science at Chan Zuckerberg Initiative &#xff08;Chan Zuckerberg Initiative是扎克伯格和他妻子Chan成立的科研&教育机构&#xff09; 研究简介 研究背景&…

微信原生小程序自定义封装组件(以导航navbar为例)

封装 topnav.js const App getApp(); Component({// 组件的属性列表properties: {pageName: String, //中间的titleshowNav: { //判断是否显示左上角的按钮 type: Boolean,value: true},showHome: { //判断是否显示左上角的home按钮type: Boolean,value: true},showLocat…

day06_Spark SQL

文章目录 day06_Spark SQL课程笔记一、今日课程内容二、DataFrame详解&#xff08;掌握&#xff09;5.清洗相关的API6.Spark SQL的Shuffle分区设置7.数据写出操作写出到文件写出到数据库 三、Spark SQL的综合案例&#xff08;掌握&#xff09;1、常见DSL代码整理2、电影分析案例…

HarmonyOS NEXT应用开发边学边玩,从零实现一影视APP(四、最近上映电影滚动展示及加载更多的实现)

在HarmonyOS NEXT开发环境中&#xff0c;我们可以使用多种组件和库来构建丰富且交互友好的应用。本文将展示如何使用HarmonyOS NEXT框架和nutpi/axios库&#xff0c;从零开始实现一个简单的影视APP的首页&#xff0c;主要关注最近上映电影的滚动展示及加载更多功能的实现。 安装…

快速、可靠且高性价比的定制IP模式提升芯片设计公司竞争力

作者&#xff1a;Karthik Gopal&#xff0c;SmartDV Technologies亚洲区总经理 智权半导体科技&#xff08;厦门&#xff09;有限公司总经理 无论是在出货量巨大的消费电子市场&#xff0c;还是针对特定应用的细分芯片市场&#xff0c;差异化芯片设计带来的定制化需求也在芯片…

基础入门-抓包技术HTTPS协议APP小程序PC应用Web证书信任转发联动

知识点&#xff1a; 1、抓包技术-Web应用-http/s-Burp&Yakit 2、抓包技术-APP应用-http/s-Burp&Yakit 3、抓包技术-PC端应用-http/s-Burp&Yakit 4、抓包技术-WX小程序-http/s-Burp&Yakit 5、抓包技术-软件联动-http/s-Proxifier 6、抓包技术-通用方案-http/s-R…

贪心算法详细讲解(沉淀中)

文章目录 1. 什么是贪心算法&#xff1f;&#xff08;贪婪鼠目寸光&#xff09;经典例题1.1.1 找零问题1.1.2最小路径和1.1.3 背包问题 2.贪心算法的特点2.1 证明例1 3.学习贪心的方向心得体会 1. 什么是贪心算法&#xff1f;&#xff08;贪婪鼠目寸光&#xff09; 贪心策略&a…

SQL面试题2:留存率问题

引言 场景介绍&#xff1a; 在互联网产品运营中&#xff0c;用户注册量和留存率是衡量产品吸引力和用户粘性的关键指标&#xff0c;直接影响产品的可持续发展和商业价值。通过分析这些数据&#xff0c;企业可以了解用户行为&#xff0c;优化产品策略&#xff0c;提升用户体验…

学会使用开源软件jclasslib 字节码文件的组成 详解

应用场景 1 应用场景 2 学习路线 以正确的姿势打开文件 字节码文件的组成 玩转字节码常用工具 以正确的姿势打开文件 开源软件 jclasslib github 地址 https://github.com/ingokegel/jclasslib 工具使用 字节码文件的组成 基本信息 常量池 字段 方法 属性 详解 魔数 主副版…

primitive 的 Appearance编写着色器材质

import { nextTick, onMounted, ref } from vue import * as Cesium from cesium import gsap from gsaponMounted(() > { ... })// 1、创建矩形几何体&#xff0c;Cesium.RectangleGeometry&#xff1a;几何体&#xff0c;Rectangle&#xff1a;矩形 let rectGeometry new…

详情页 路由传值

路由传值获取参数 渲染数据 主页面 <template><div class"km"><div v-for"item in items" :key"item.id"><div class"title-km" ><img :src"item.imageUrl" alt"Image" class"…

OpenCV基础:矩阵的创建、检索与赋值

本文主要是介绍如何使用numpy进行矩阵的创建&#xff0c;以及从矩阵中读取数据&#xff0c;修改矩阵数据。 创建矩阵 import numpy as npa np.array([1,2,3]) b np.array([[1,2,3],[4,5,6]]) #print(a) #print(b)# 创建全0数组 eros矩阵 c np.zeros((8,8), np.uint8) #prin…

解锁未来情感科技:AI 机器人 Ropet 搭载的前沿智能黑科技

2025年的国际消费电子产品展览会&#xff08;CES&#xff09;上&#xff0c;一只可爱的“毛绒玩具”成了全场焦点。 当然&#xff0c;这并不是一个单纯的玩偶&#xff0c;而是和《超能陆战队》的大白一样温暖的陪伴机器人。 相信有很多人和小编一样&#xff0c;当年看完《超能…

软件测试 —— Selenium常用函数

软件测试 —— Selenium常用函数 操作测试对象点击/提交对象 click()模拟按键输入 send_keys("")清除文本内容 clear() 模拟用户键盘行为 Keys包示例用法 获取文本信息 textget_attribute("属性名称") 获取当前页面标题 title获取当前页面的 url current_u…

【WEB】网络传输中的信息安全 - 加密、签名、数字证书与HTTPS

文章目录 1. 概述2. 网络传输安全2.1.什么是中间人攻击2.2. 加密和签名2.2.1.加密算法2.2.2.摘要2.2.3.签名 2.3.数字证书2.3.1.证书的使用2.3.2.根证书2.3.3.证书链 2.4.HTTPS 1. 概述 本篇主要是讲解讲一些安全相关的基本知识&#xff08;如加密、签名、证书等&#xff09;&…

服务器数据恢复—EMC存储POOL中数据卷被删除的数据恢复案例

服务器数据恢复环境&故障&#xff1a; EMC Unity 400存储连接了2台硬盘柜。2台硬盘柜上一共有21块硬盘&#xff08;520字节&#xff09;。21块盘组建了2组RAID6&#xff1a;一组有11块硬盘&#xff0c;一组有10块硬盘。 在存储运行过程中&#xff0c;管理员误操作删除了 2组…

python 轮廓 获取环形区域

目录 效果图&#xff1a; 代码&#xff1a; 效果图&#xff1a; 代码&#xff1a; import cv2 import numpy as np# 读取图像 image cv2.imread(rE:\project\jijia\tools_jijia\img_tools\ground_mask.jpg, cv2.IMREAD_GRAYSCALE) # 二值化图像 # 二值化图像 _, binary cv…

使用 WPF 和 C# 将纹理应用于三角形

此示例展示了如何将纹理应用于三角形,以使场景比覆盖纯色的场景更逼真。以下是为三角形添加纹理的基本步骤。 创建一个MeshGeometry3D对象。像往常一样定义三角形的点和法线。通过向网格的TextureCoordinates集合添加值来设置三角形的纹理坐标。创建一个使用想要显示的纹理的 …

算法妙妙屋-------2..回溯的奇妙律动

回溯算法是一种用于系统性地搜索和解决问题的算法&#xff0c;它以深度优先搜索&#xff08;DFS&#xff09;为基础&#xff0c;用来探索所有可能的解决方案。通过递归地尝试候选解并在必要时回退&#xff08;即“回溯”&#xff09;&#xff0c;它能够高效地解决许多涉及组合、…

如何在Jupyter中快速切换Anaconda里不同的虚拟环境

目录 介绍 操作步骤 1. 选择环境&#xff0c;安装内核 2. 注册内核 3. 完工。 视频教程 介绍 很多网友在使用Jupyter的时候会遇到各种各样的问题&#xff0c;其中一个比较麻烦的问题就是我在Anaconda有多个Python的环境里面&#xff0c;如何让jupyter快速切换不同的Pyt…