JavaScript对象的属性描述符(Property Descriptor)介绍

news2024/10/5 17:22:30

JavaScript对象的属性描述符(Property Descriptor)介绍

JavaScript 中的对象(Object)是一个包含相关数据和方法的集合,通常由一些变量和函数组成,我们称之为对象里面的属性(property)和方法(method)。

【在JavaScript中,一般将Property译为属性、attribute译为特性,或不加区分都译为属性。】

本文重点介绍JavaScript对象的属性。

JavaScript 属性(property)概述

JavaScript 属性(property)是一个对象的成员,包含以下组成部分:

一个名称(也叫做键),它可能是字符串或符号值。

一个值,它可以是任何 JavaScript 值。具有函数值的属性也可以称为方法。

一些特性(attribute),它们指定了属性的读取和写入方式。属性可能具有 configurable、enumerable 和 writable 特性(attributes)。

【见 https://developer.mozilla.org/zh-CN/docs/Glossary/Property/JavaScript 】

在JS中,对象的属性(property)也称为名值对(键/值对),包括属性名和属性值。属性名可以是包含空字符串在内的任意字符串,一个对象中不能存在两个同名的属性。属性值可以是任意类型的数据。关于JavaScript 属性(property)可参见 https://blog.csdn.net/cnds123/article/details/125406135

本文重点介绍属性描述符。

属性描述符(Property Descriptor

ES5中定义了一个属性描述符对象(property descriptor)。其作用是给对象的属性增加更多的控制。

【Property Descriptor(属性描述符),也有人称为Property Attributes。】

描述符分类

configurable

enumerable

value

writable

get

set

数据描述符

可以

可以

可以

可以

不可以

不可以

存取描述符

可以

可以

不可以

不可以

可以

可以

JavaScript的数据描述符和访问器描述符都是对象。它们共享以下可选键(请注意:这里提到默认值是指在使用 Object.defineProperty() 定义属性时的默认值):

configurable

当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。 默认为 false。

enumerable

当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。 默认为 false。

数据描述符还具有以下可选键:

value

该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。 默认为 undefined。

writable

当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符 (en-US)改变。 默认为 false。

存取描述符还具有以下可选键:

get

属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。 默认为 undefined。

set

属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。 默认为 undefined。

更多关于属性描述符类型(property descriptor types )以及他们特/属性(attributes)的信息可以查看https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

描述符方法用于设置属性描述符。描述符方法常用的有:

Object.defineProperty(obj, name, descriptor)方法用于创建或配置对象的一个属性描述符,返回配置后的对象。

Object.defineProperties(obj, descriptors)方法用于创建或配置对象的多个描述符,返回配置后的对象。

Object.preventExtensions(object)方法防止向对象添加属性。

Object.seal(object)方法防止向对象添加属性。

Object.freeze(object)方法防止对对象进行任何更改。

Object.getOwnPropertyDescriptor(obj, name)方法用于查询对象一个属性的描述符,查询结果以对象的形式返回。

属性描述符的使用讲解

Object.defineProperty()方法

Object.defineProperty()方法可以为对象添加属性,或者修改现有属性。如果指定的属性名在对象中不存在,则执行添加操作;如果在对象中存在同名属性,则执行修改操作。

使用属性描述符的基本语法如下:

Object.defineProperty(object, propertyname, descriptor);

参数说明如下:

object:指定要添加或修改属性的对象,可以是 JavaScript 对象或者 DOM 对象。

propertyname:表示属性名的字符串。

descriptor:定义属性的描述符,包括对数据属性或访问器属性。

返回值为已修改的对象。

【Object.defineProperty方法,可见 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty】

从一段简单的代码讲起:

var obj = { };

Object.defineProperty(obj, 'attr', { value: 1 });

上面代码给obj对象增加了一个名为attr的属性,值为1。相当于:

var obj = { };

obj.attr = 1;

相比起来,Object.defineProperty 的写法看似更为复杂。但是,它最大的奥秘在于其第三个参数。现在看看使用属性的描述符的情况:

let obj = { };
Object.defineProperty(obj, 'property1', {
    value: 10,
    writable: false
});
console.log(obj.property1); //10
obj.property1 = 20; // 注意该句不影响obj.property1的值
console.log(obj.property1); //10

为了测试上面JavaScript程序代码,我在这里将其放在标签

<script>

</script>之间

保存文件名为:JS对象描述符writables示例.html,用浏览器打开它,再按下 F12键打开浏览器的“控制台”(console) 面板,显示效果如下:

看到了吗?执行以上程序可以发现,两次输出的property1的值都是10.

这样的结果会有点莫名其妙,赋值语句的执行没报异常,又不影响obj.property1的值。如果在大段的代码中出现这样的问题,很难排查出来。有什么应对吗?只要以严格模式运行代码,就会产生异常。

【严格模式是在 ECMAScript5(ES5)中引入的,在严格模式下,JavaScript 对语法的要求会更加严格,一些在正常模式下能够运行的代码,在严格模式下将不能运行。

要启用严格模式,您只需要在JavaScript程序代码的开头添加"use strict";或'use strict';指令即可】

将上面代码改为:

'use strict'; // 进入严格模式
let obj = { };
Object.defineProperty(obj, 'property1', {
    value: 10,
    writable: false
});
console.log(obj.property1); //10
obj.property1 = 20; // 注意该句报异常(throw exception)

为了测试上面代码,将其放在标签

<script>

</script>之间

保存文件名为:JS对象描述符writables示例(严格模式).html,用浏览器打开它,再按下 F12键打开浏览器的“控制台”(console) 面板,显示效果如下:

现在看看数据描述符 enumerable的作用,它可以控制属性是否能被枚举,示例源码如下:

<script>
var obj = {
    str1: "a",
    str2: "bb",
    str3: "ccc"
};
Object.defineProperty(obj, "str2", {enumerable:false}); // 请注意此句的作用
for (var i in obj) { 
   console.log(obj[i]); 
}
</script>

保存文件名为:JS对象描述符enumerable示例.html,用浏览器打开它,再按下 F12键打开浏览器的“控制台”(console) 面板,显示效果如下:

现在介绍存取描述符get、set

getter和setter取代了数据属性中的value和writable属性。

如果只设置了set方法,读取对象的属性值会返回undefined。通常set和get方法成对出现。

示例源码如下:

<script>
let o = {};
Object.defineProperty(o, 'a', {
  configurable: true,
  enumerable: true,
  get: function() {
    return 10
  }
})

console.log(o.a) // 10
o.a = 20
console.log(o.a) // 10
</script>

保存文件名为:JS存取描述符get和set示例.html,用浏览器打开它,再按下 F12键打开浏览器的“控制台”(console) 面板,显示效果如下:

 这两个描述符的使用就有很大的想象空间了,如,可以用来校验输入值,看下面这个例子:

<script>
let obj = { realAge: 0 }

Object.defineProperty(obj, 'age', {
    get: function() {
        return this.realAge
    },
    set: function(value) {
        const temp = Number(value);
        if(isNaN(temp)) 
              throw TypeError('Not A Number')  //检测存入的值,如果无法转换成数字就会抛出自定义异常
        this.realAge = temp;
    }
})

obj.age = '22'
console.log(obj.age) // 22
obj.age='abc';  //引发异常
console.log(obj.age) // TypeError:Not A Number
</script>

保存文件名为:JS存取描述符get和set示例2.html,用浏览器打开它,再按下 F12键打开浏览器的“控制台”(console) 面板,显示效果如下:

上例可以采用如下便捷写法: 

<script>
let obj = { 
    realAge: 0,
    get age() {  // 函数名 age 就是属性名
        return this.realAge
    },
    set age(value) { // 函数名 age 就是属性名
        const temp = Number(value);
        if(isNaN(temp)) 
              throw TypeError('Not A Number')  //检测存入的值,如果无法转换成数字就会抛出自定义异常
        this.realAge = temp;
    }
}

obj.age = '22'
console.log(obj.age) // 22
obj.age='abc';  //引发异常
console.log(obj.age) // TypeError:Not A Number
</script>

你可以保存文件名为:JS存取描述符get和set示例2b.html,用浏览器打开它测试看看。

前面介绍了设置属性描述符,那如何获取已设置的描述符呢?

Object.getOwnPropertyDescriptor方法

使用 Object.getOwnPropertyDescriptor() 方法能够获取对象属性的描述符。具体用法如下:

Object.getOwnPropertyDescriptor(object, propertyname);

参数 object 表示指定的对象,propertyname 表示属性的名称。

返回值为属性的描述符对象。

示例源码如下:

<script>
let obj = { 
     a: 10,
     say: function(){
          return 'Hello'; 
     }
};

let desc1 = Object.getOwnPropertyDescriptor(obj, 'a'); //获取描述符状况
console.dir(desc1);
let desc2 = Object.getOwnPropertyDescriptor(obj, 'a'); //获取描述符状况
console.dir(desc2);
</script>

保存文件名为:JS获取描述符状况.html,用浏览器打开它,再按下 F12键打开浏览器的“控制台”(console) 面板,显示效果如下:

 

参考
中文 https://www.w3schools.cn/js/js_object_es5.html【英文 https://www.w3schools.com/js/js_object_es5.asp】
畅谈JS属性描述符和Proxy https://zhuanlan.zhihu.com/p/355217413
属性描述器https://blog.51cto.com/u_15069482/4171311

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

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

相关文章

java springboot工程RESTful入门案例 认识请求类型 参数

我们先创建一个java的springboot工程 然后 我们先用老方式试一下 在启动类的同级创建目录controller 下面创建一个类 叫 UserController 参考代码如下 package com.example.threshold.controller;import org.springframework.web.bind.annotation.GetMapping; import org.spri…

负载均衡与DNS轮询

负载均衡 load balance 负载均衡&#xff08;Load Balancing&#xff09;是一种将工作负载&#xff08;Workload&#xff09;分摊到多个计算资源&#xff08;服务器、存储设备、网络设备等&#xff09;上的技术&#xff0c;目的是提高系统的可用性、性能和扩展性。负载均衡可以…

序列化和反序列化二叉树 -----前序,中序,后序,层序

目录 一.序列化和反序列化 1.什么是序列化和反序列化 二.前序遍历 1.序列化 1.问题分析 2.代码实现 2.反序列化 1.问题分析 2.代码实现 三.后序遍历 1.序列化 1.思路分析 2.代码实现 2.反序列化 1.思路分析 2.代码实现 四.中序遍历 1.序列化 1.思路分析 2.代…

SpringBoot 使用Prometheus采集自定义指标数据

一、我们需要什么指标 对于DDD、TDD等&#xff0c;大家比较熟悉了&#xff0c;但是对于MDD可能就比较陌生了。MDD是Metrics-Driven Development的缩写&#xff0c;主张开发过程由指标驱动&#xff0c;通过实用指标来驱动快速、精确和细粒度的软件迭代。MDD可使所有可以测量的东…

RPC调用框架简单介绍

一.Thrift Apache Doris目前使用的RPC调度框架。Thrift是一款基于CS&#xff08;client -server&#xff09;架构的RPC通信框架&#xff0c;开发人员可以根据定义Thrift的IDL(interface decription language)文件来定义数据结构和服务接口&#xff0c;灵活性高&#xff0c;支持…

Leetcode.2583 二叉树中的第 K 大层和

题目链接 Leetcode.2583 二叉树中的第 K 大层和 Rating &#xff1a; 1374 题目描述 给你一棵二叉树的根节点 root和一个正整数 k 。 树中的 层和 是指 同一层 上节点值的总和。 返回树中第 k 大的层和&#xff08;不一定不同&#xff09;。如果树少于 k 层&#xff0c;则返…

INFINONE XC164单片机逆向记录(5)C166地址系统

本人所写的博客都为开发之中遇到问题记录的随笔,主要是给自己积累些问题。免日后无印象,如有不当之处敬请指正(欢迎进扣群 24849632 探讨问题); 写在专栏前面https://blog.csdn.net/Junping1982/article/details/129955766 INFINONE XC164单片机逆向记录(1)资料准备

Python爬虫知识回顾

之前一直沉溺于java&#xff0c;jsp&#xff0c;ssh&#xff0c;db等爬虫&#xff0c;现在又要开始走python的老路了。常用的requests库&#xff0c;通过requests对象的get方法&#xff0c;获取一个response对象。jsp的东西。 其中timeout,proxies,headers,cookies,verify,是我…

webgl-画指定颜色三角形

html <!DOCTYPE html> <head> <style> *{ margin: 0px; padding: 0px; } </style> </head> <body> <canvas id webgl> 您的浏览器不支持HTML5,请更换浏览器 </canvas> <script src"./main.js"></script&g…

JUC之CountDownLatch与CyclicBarrier

1.前言 在java.util.concurrent包中为我们提供了很多的线程同步工具类&#xff0c;例如CountDownLatch与CyclicBarrier&#xff0c;那么它们主要的用途是什么呢&#xff1f;且看后续分析。 2.CountDownLatch 2.1 什么是CountDownLatch CountDownLatch&#xff0c;顾名思义&…

从ReentrantLock角度解析AQS

一、概述 闲来不卷&#xff0c;随便聊一点。 一般情况下&#xff0c;大家系统中至少也是JDK8了&#xff0c;那想必对于JDK5加入的一系列功能并不陌生吧。那时候重点加入了java.util.concurrent并发包&#xff0c;我们简称为JUC。JUC下提供了很多并发编程实用的工具类&#xf…

风光及负荷多场景随机生成与缩减

目录 1 主要内容 计算模型 场景生成与聚类方法应用 2 部分程序 3 程序结果 4 程序链接 1 主要内容 该程序方法复现了《融合多场景分析的交直流混合微电网多时间尺度随机优化调度策略》3.1节基于多场景技术的随机性建模部分&#xff0c;该部分是随机优化调度的重要组成部分…

记录-css实现交融文字效果

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 CSS是有魔法的&#xff0c;我们今天来实现一个CSS的动画效果&#xff0c;只需要几行代码就可以搞定。 第一步、我们要将一行文字从中间展开 <!DOCTYPE html> <html lang"en"> &…

面试官:聊聊js原型

一分钟了解原型对象 js分为函数对象和普通对象 &#xff0c;每个对象都有__proto__属性&#xff0c;但是只有函数对象才有prototype属性&#xff0c;prototype属性就是函数的原型对象。 比如说 构造函数通过new 实化一个实例对象&#xff0c;实例对象的__proto__ 指向原型对象…

NumPy 基础知识 :6~10

原文&#xff1a;Numpy Essentials 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 六、NumPy 中的傅立叶分析 除其他事项外&#xff0c;傅立叶分析通常用于数字信号处理。 这要归功于它在将输入信号&#xff08;时域&#xff09;分离为以离散频率&#xff08;频域&am…

Spring Boot集成Druid实现多数据源的两种方式

目录 项目场景&#xff1a; 一、集成com.baomidou的方式 1、maven依赖&#xff1a; 2、 配置文件&#xff1a; 3、 使用注解切换数据源&#xff1a; 二、基于AOP手动实现多数据源原生的方式 1、maven依赖&#xff1a; 2、 配置文件&#xff1a; 3、 多数据源名称类 4…

数字中国理念引领国企人力资源数字化转型与实践

3月初&#xff0c;《数字中国建设整体布局规划》出台&#xff0c;作为中国数字经济发展的重要指导性文件&#xff0c;规划提出了数字中国建设的总体目标和战略方向&#xff0c;文件详细阐述了数字中国内涵&#xff0c;包含数字经济、数字社会、数字政府以及数字生态等内涵。《规…

制造企业该如何选择MES生产管理系统?盘点四大生产管理系统软件

本文将介绍&#xff1a;1、如何选择MES(生产管理系统&#xff09;&#xff1b;2、盘点四款好用的生产管理系统 生产管理系统即MES(Manufacturing Execution System)&#xff0c;制造执行系统。是面向车间生产的管理系统。在产品从工单发出到成品完工的过程中&#xff0c;MES系…

1206. 设计跳表

1206. 设计跳表 不使用任何库函数&#xff0c;设计一个 跳表 。 跳表 是在 O(log(n)) 时间内完成增加、删除、搜索操作的数据结构。跳表相比于树堆与红黑树&#xff0c;其功能与性能相当&#xff0c;并且跳表的代码长度相较下更短&#xff0c;其设计思想与链表相似。 例如&a…

如何收集EMC VPLEX 日志和VPLEX日志的简单解读

对于VPLEX遇到的问题&#xff0c;和二线沟通最快最有效的办法就是收集完整的日志&#xff0c;而不是拍一个照片。本文就详细介绍如何收集日志&#xff1f;和那些日志文件对我们分析问题是有价值的。 命令行ssh登录Vplex 管理控制台&#xff0c;然后进入Vplexcli命令行&#xf…