深入理解 JavaScript 对象、属性、解构和增强语法
ECMA-262将对象定义为一组属性的无序集合。
1 内部属性描述
1.1 数据属性
[[Configurable]]:可配置性,直接定义在对象的属性该特性默认为true,表示可以对属性进行删除、修改等操作。[[Enumerable]]:可枚举性,直接定义在对象的属性该特性默认为true,它决定了我们是否可以通过for-in循环遍历对象的属性。[[Writable]]:可写性,直接定义在对象的属性该特性默认为true,表示属性的值是否可以被修改。[[Value]]:属性的实际数据值,默认为undefined。
我们可以使用Object.defineProperty来定义数据属性。
let student1 = { name: "student1" };
Object.defineProperty(student1, "sex", {configurable: false,enumerable: false,writable: false,value: "male",
});
//测试可配置性
delete student1.sex;
console.log(student1.sex);
console.log();
//测试可枚举性
for (const key in student1) {console.log(key + " ");
}
console.log();
//测试可写性
student1.sex = "female";
console.log(student1.sex);
输出:
malenamemale
除了属性configurable属性为false的情况,我们可以多次调用defineProperty。
如果调用了defineProperty但不指定configurable、enumerable、writable的值,则它们默认被设为false。
1.2 访问器属性
[[Configurable]]:表示属性是否可修改。直接定义在对象的属性该特性默认为true。[[Enumberable]]:表示属性是否可枚举。直接定义在对象的属性该特性默认为true。[[Get]]:获取属性时调用的函数。默认为undefined。[[Set]]:设置属性时调用的函数。默认为undefined。
同样我们使用Object.defineProperty来定义访问器属性。
let person = {firstName: "John",lastName: "Doe",
};
Object.defineProperty(person, 'fullName', {get() {return this.firstName + " " + this.lastName;},set(value) {const parts = value.split(" ");this.firstName = parts[0];this.lastName = parts[1];}
});
console.log(person.fullName);
person.fullName = "Jane Smith";
console.log(person.firstName);
console.log(person.lastName);
输出:
John Doe
Jane
Smith
访问器属性和数据属性的不同之处在于:
数据属性关注于数据的值与可写性,访问器属性关注获取和设置数据时进行的操作。
2 定义多个属性
可以使用Object.defineProperties一次性定义多个属性。
let person={};
Object.defineProperties(person,{name:{value: 'Jane'},age:{get(){return this.age;},set(value){this.age=value;}}
});
3 读取属性特性
使用Object.getOwnPropertyDescriptor读取属性的属性描述符。
使用上面一节中定义好的person对象。
let descriptor1=Object.getOwnPropertyDescriptor(person,'name');
console.log('descriptor1.configurable:'+descriptor1.configurable);
console.log('descriptor1.enumerable:'+descriptor1.enumerable);
console.log('descriptor1.writable:'+descriptor1.writable);
console.log('descriptor1.value:'+descriptor1.value);
let descriptor2=Object.getOwnPropertyDescriptor(person,'age');
console.log('descriptor2.configurable:'+descriptor2.configurable);
console.log('descriptor2.enumerable:'+descriptor2.enumerable);
console.log('descriptor2.get:'+descriptor2.get);
console.log('descriptor2.set:'+descriptor2.set);
运行结果:
descriptor1.configurable:false
descriptor1.enumerable:false
descriptor1.writable:false
descriptor1.value:Jane
descriptor2.configurable:false
descriptor2.enumerable:false
descriptor2.get:get() {return this.age;}
descriptor2.set:set(value) {this.age = value;}
注意到没有设置的configurable、enumerable、writable都被设置为false。
4 合并对象
合并对象即将一个对象的属性复制到目标对象上,这也被称为混入(mixin)。学过Vue的知道,Vue里面也有个混入的概念,Vue2 混入。
ES6提供Object.assign()方法来合并对象。
该方法将一个或多个源对象的可枚举和自有属性复制到目标对象上。
- 可枚举判断:Object.propertyIsEnumerable()。
- 自有属性判断:Object.hasOwnProperty()。
复制的具体操作是调用源对象的get获取属性,再调用目标对象的set属性。
const target = {_a:'',// set a(val) {// console.log("调用target属性a的set");// this._a = val;// }
};
Object.defineProperty(target, 'a', {set(val) {console.log('调用target属性a的set');this._a = val;},
});
const source1 = {// get a() {// console.log("调用source1属性a的get");// return "a";// }
};
Object.defineProperty(source1, "a", {get() {console.log("调用source1属性a的get");return "a";},enumerable: true
});
const source2 = { b: 'b' };
Object.assign(target, source1, source2);
console.log(target);
在字面中定义的属性的未设置的数据属性和访问器属性都为默认值,而在Object.defineProperty中定义的属性的未设置的特性要么为false,要么为undefined。
上面我们给source1的访问器属性a设置enumerable: true就是这个原因,不然无法复制a属性。
运行结果:
调用source1属性a的get
调用target属性a的set
{ _a: 'a', b: 'b' }
Object.assign还有以下注意的地方:
-
同名的属性,后面的会覆盖前面的。
-
Object.assign是浅复制,即只复制对象内部元素的引用。
const originalObject={a:1} const anotherShallowCopy = Object.assign({}, originalObject); console.log(anotherShallowCopy === originalObject);//false console.log(anotherShallowCopy.a === originalObject.a);//true -
在复制过程出现错误,Object.assign不会回滚到初始状态。
5 严格相等判断
大多数情况我们可以使用===来判断严格相等,但以下的特殊边界情况却不尽人意:
console.log(+0 === -0); //true
console.log(+0 === 0); //true
console.log(-0 === 0); //true
console.log(NaN === NaN); //false
其中NaN表示Not a Number,可以使用全局函数isNaN检查。
ES6提供了Object.is来应对上述所有情况。
Object.is(v1,v2);
使用递归+Object.is+剩余参数比较多个值的相等性:
function areValuesEqual(a,...values){return Object.is(a,values[0])&&(values.length<2||areValuesEqual(...values));
}
或者使用every:
function areValuesEqual(a, ...values) {return values.every(value => Object.is(a, value));
}
6 增强的对象语法
6.1 属性值的简写
const name = "John";
const age = 30;// 使用属性值简写创建对象
const person = {name,age,sayHello() {console.log(`Hello, my name is ${this.name}.`);}
};console.log(person); // 输出 { name: 'John', age: 30 }
person.sayHello(); // 输出 "Hello, my name is John."
6.2 可计算属性
可计算属性允许你在定义对象时在方括号内使用表达式来定义对象名。
const methodSuffix = "Hello";const dynamicObject = {["say" + methodSuffix]() {console.log("Hello, World!");}
};dynamicObject.sayHello(); // 输出 "Hello, World!"
6.3 简写属性名
let key='Age';
let person={_name: 'Jane',_age: '18',get name(){return this._name;},set name(val){this._name=val;},sayHello() {console.log(`Hello, my name is ${this._name}.`);},['say'+key](){console.log(`Hello, my age is ${this._age}.`);}
};
7 对象解构
对象解构指可以使用与对象匹配的结构来实现对象属性赋值。
let person={name: 'Jane',age: 18
};
//别名
let {name:personName,age:personAge}=person;
//属性简写
let {name,age}=person;
//没有匹配的属性被赋值为undefined
let {name,age,height}=person;
//解构时赋值
let {name,age,height=180}=person;
解构的本质是使用ToObject函数将元数据转为对象。
因此,null和undefined不能被解构。
如果给事先声明好的变量赋值,则解构表达式整个需要包裹在一对括号里。
1)嵌套解构
let {outer:{inter}}=obj;
2)部分解构
解构像我们的对象合并一样,是尽力而为的行为,一旦解构过程发生错误,过程终止且无法回滚,也就是只解构了部分。
3)对象解构为函数参数
function sum([a, b]) {return a + b;
}const numbers = [3, 5];console.log(sum(numbers)); // 输出 8
相关文章:
深入理解 JavaScript 对象、属性、解构和增强语法
ECMA-262将对象定义为一组属性的无序集合。 1 内部属性描述 1.1 数据属性 [[Configurable]]:可配置性,直接定义在对象的属性该特性默认为true,表示可以对属性进行删除、修改等操作。[[Enumerable]]:可枚举性,直接定…...
2023年IT服务行业研究报告
第一章 行业概况 1.1 定义 IT服务行业是一个广泛的术语,涵盖了所有提供技术支持和服务的公司。这些服务包括系统集成,云计算服务,软件和硬件支持,网络服务,咨询服务,以及一系列其他类型的技术服务。此外&…...
腾讯云服务器镜像TencentOS Server有用过的吗?
腾讯云服务器镜像TencentOS Server操作系统有用过的吗?踩过坑吗?TencentOS性能和稳定性如何?TencentOS Server与CentOS保持兼容,在稳定性、性能、容器基础设施等核心能力方面做了全面的增强和优化,能为企业提供稳定高可…...
小区村庄集中生活废水处理设备厂家直销价格
小区村庄集中生活废水处理设备厂家直销价格 设备的构造 1、填料 该填料选用特制塑料和树脂组成,结构科学、新颖、填料比表面积达1000m2/m3,比重轻0.97g/cm3,不堵塞、易挂膜。 该填料是由纤细球体,网络外壳和通心多孔柱体组成的球形…...
Redisson实现分布式锁案例
Redisson实现分布式锁案例 引入依赖 <dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.23.2</version> </dependency>创建Redisson配置类 Configuration pub…...
Generated Knowledge Prompting for Commonsense Reasoning
本文是知识图谱系列相关的文章,针对《Generated Knowledge Prompting for Commonsense Reasoning》的翻译。 常识推理的生成知识提示 摘要1 引言2 生成知识提示3 实验设置4 实验结果5 相关工作6 结论 摘要 结合外部知识是否有利于常识推理,同时保持预训…...
mybatisPlus多数据源方案
背景 在微服务李娜一般一个服务只有一个数据源,但是在有的老项目或者一些特定场景需要多数据源链接不同的数据库,本文以mybatisPlus为基础给出解决方案 多数据源场景分类 情形一:项目启动就确定了情形一:一些sass系统里面动态确…...
MonoDETR: Depth-guided Transformer for Monocular 3D Object Detection 论文解读
MonoDETR论文解读 abstract 单目目标检测在自动驾驶领域,一直是一个具有挑战的任务。现在大部分的方式都是沿用基于卷积的2D 检测器,首先检测物体中心,后通过中心附近的特征去预测3D属性。 但是仅仅通过局部的特征去预测3D特征是不高效的&…...
Vulnhub内网渗透DC-7靶场通关
个人博客: xzajyjs.cn DC系列共9个靶场,本次来试玩一下一个 DC-7,下载地址。 下载下来后是 .ova 格式,建议使用vitualbox进行搭建,vmware可能存在兼容性问题。靶场推荐使用NAT(共享)模式,桥接模式可能会造成目标过多不…...
acunetix2023安装教程
1、解压之后一键安装exe文件 2、将解压出来的Awv2023.6[Windows]文件夹下的wvsc.exe文件放置于AWVS安装目录,与原文件进行替换,如图所示。(注:如果是默认安装,则文件位置位于C:\Program Files (x86)\Acunetix\14.2.210…...
pytest pytest.ini 配置日志输出至文件
创建pytest.ini 文件 [pytest] log_file pytest_log.txt log_file_level INFO log_file_date_format %Y-%m-%d %H:%M:%S log_file_format %(asctime)s | %(filename)s | %(funcName)s | line:%(lineno)d | %(levelname)s | %(message)s import pytest import loggingdef …...
Linux脚本-将当前文件夹下所有包含main函数的.c文件提取出来
实现一个Linux脚本,该脚本使用 for 循环遍历当前目录下的所有 .c 文件。 对于每个 .c 文件,使用 grep 命令来查找是否包含字符串 “main”。 如果该 .c 文件包含 “main”,则输出到/home/majn/llvm_project/extract_main目录下。 #!/bin/bas…...
Spring依赖注入(DI)
目录 构造器注入 set注入 拓展注入 bean的作用域 Singleton Prototype Dependency Injection 依赖 : 指Bean对象的创建依赖于容器 . Bean对象的依赖资源 . 注入 : 指Bean对象所依赖的资源 , 由容器来设置和装配 . 构造器注入 具体实现:SpringIOC创建对象的…...
论文笔记: 深度学习速度模型构建的层次迁移学习方法 (未完)
摘要: 分享对论文的理解, 原文见 Jrome Simon, Gabriel Fabien-Ouellet, Erwan Gloaguen, and Ishan Khurjekar, Hierarchical transfer learning for deep learning velocity model building, Geophysics, 2003, R79–R93. 这次的层次迁移应该指从 1D 到 2D 再到 3D. 摘要 深…...
苹果为 Vision Pro 头显申请游戏手柄专利
苹果Vision Pro 推出后,美国专利局公布了两项苹果公司申请的游戏手柄专利,其中一项的专利图如下图所示。据 PatentlyApple 报道,虽然申请专利并不能保证苹果公司会推出游戏手柄,但是苹果公司同时也为游戏手柄申请了商标࿰…...
【数据结构】多叉树转换为二叉树-c++代码实现-POJ 3437 Tree Grafting
文章目录 写这个题目的原因寻找提交网址题目解决思路AC代码成功AC 写这个题目的原因 1、今天在看王道考研数据结构的课(虽然我要保研,但是因为这些看保研面试的时候会问,所以看一下嘞orz),看到了这个多叉树转换为二叉…...
ASP.NET Core 中基于 Controller 的 Web API
基于 Controller 的 Web API ASP.NET Wep API 的请求架构 客户端发送Http请求,Contoller响应请求,并从数据库读取数据,序列化数据,然后通过 Http Response返回序列化的数据。 ControllerBase 类 Web API 的所有controllers 一般…...
iOS系统修复软件 Fix My iPhone for Mac
Fix My iPhone for Mac是一款iOS系统恢复工具。修复您的iPhone卡在Apple徽标,黑屏,冻结屏幕,iTunes更新/还原错误和超过20个iOS 12升级失败。这个macOS桌面应用程序提供快速,即时的解决方案来修复您的iOS系统问题,而不…...
Git企业开发控制理论和实操-从入门到深入(七)|企业级开发模型
前言 那么这里博主先安利一些干货满满的专栏了! 首先是博主的高质量博客的汇总,这个专栏里面的博客,都是博主最最用心写的一部分,干货满满,希望对大家有帮助。 高质量博客汇总 然后就是博主最近最花时间的一个专栏…...
15. 卡牌游戏
目录 题目 思路 C整体代码(含详细注释) 题目 Description 小张在玩一种卡牌游戏,牌组由张牌组成,其中张上写有数字各一张,其余张上全部是数字。 现在牌组经过随机打乱后,小张拿走其中张牌作为手牌&#…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
