2023/02/18 ES6对象属性的解读

news2024/9/27 12:08:48

1 属性的可枚举性和遍历

<script>
    const obj = {
        userName: 'zhaoshuai-lc',
        userAge: 26,
        userSex: 'male'
    }
    let res = Object.getOwnPropertyDescriptors(obj);
    console.log(res);
</script>

在这里插入图片描述
描述对象的 [ enumerable ] 属性, 称为“可枚举性”, 如果该属性为 [ false ], 就表示某些操作会忽略当前属性.

1 for...in循环: 只遍历对象自身的和继承的可枚举的属性.
2 Object.keys(): 返回对象自身的所有可枚举的属性的键名.
3 JSON.stringify(): 只串行化对象自身的可枚举的属性.
4 Object.assign(): 忽略enumerable为false的属性, 只拷贝对象自身的可枚举的属性.
<script>
    const obj = {
        userName: 'zhaoshuai-lc',
        userAge: 26,
        userSex: 'male'
    }
    for (const key in obj) {
        console.log(key, " : ", obj[key]);
    }
    // return string[]
    let objStr = Object.keys(obj);
    console.log(objStr);

    // return string
    let json = JSON.stringify(obj);
    console.log(json);

</script>

这四个操作之中, 前三个是 ES5 就有的, 最后一个 [ Object.assign() ] 是 ES6 新增的. 其中, 只有for…in会返回继承的属性, 其他三个方法都会忽略继承的属性, 只处理对象自身的属性. 实际上, 引入“可枚举”(enumerable)这个概念的最初目的, 就是让某些属性可以规避掉for…in操作, 不然所有内部属性和方法都会被遍历到. 比如, 对象原型的toString方法, 以及数组的length属性, 就通过“可枚举性”, 从而避免被for…in遍历到.

Object.getOwnPropertyDescriptor(Object.prototype, 'toString').enumerable
// false
Object.getOwnPropertyDescriptor([], 'length').enumerable
// false

上面代码中, toString和length属性的enumerable都是false, 因此for…in不会遍历到这两个继承自原型的属性.
另外 , ES6 规定, 所有 Class 的原型的方法都是不可枚举的.

    Object.getOwnPropertyDescriptor(class {
        foo() {
        }
    }.prototype, 'foo').enumerable
    // false

总的来说, 操作中引入继承的属性会让问题复杂化, 大多数时候, 我们只关心对象自身的属性. 所以, 尽量不要用 [ for…in ] 循环, 而用 [ Object.keys() ] 代替.

2 属性的遍历方法

<script>
    const obj = {
        userName: 'zhaoshuai-lc',
        userAge: 26,
        userSex: 'male'
    }
    // for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性).
    console.log('const key in obj')
    for (const key in obj) {
        console.log(key, " : ", obj[key]);
    }
    // return string[]
    // Object.keys返回一个数组, 包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名.
    let objStr = Object.keys(obj);
    console.log('Object.keys(obj) : ', objStr);

    // return string[]
    // Object.getOwnPropertyNames返回一个数组, 包含对象自身的所有属性(不含 Symbol 属性, 但是包括不可枚举属性)的键名.
    let propertyNames = Object.getOwnPropertyNames(obj);
    console.log('Object.getOwnPropertyNames(obj) : ', propertyNames);

    // return symbol[]
    // Object.getOwnPropertySymbols返回一个数组, 包含对象自身的所有 Symbol 属性的键名.
    let propertySymbols = Object.getOwnPropertySymbols(obj);
    console.log('Object.getOwnPropertySymbols(obj) : ', propertySymbols);

    // return (string | symbol)[]
    // Reflect.ownKeys返回一个数组, 包含对象自身的(不含继承的)所有键名, 不管键名是 Symbol 或字符串, 也不管是否可枚举.
    let ownKeys = Reflect.ownKeys(obj);
    console.log('Reflect.ownKeys(obj) : ', ownKeys);
</script>

在这里插入图片描述

3 super 关键字

我们知道, this关键字总是指向函数所在的当前对象 , ES6 又新增了另一个类似的关键字 [ super ], 指向当前对象的原型对象.

1 原型链实现继承 (bad)

<script>
    <!--    父类型-->
    function Supper() {
        this.supPro = 'Supper property'
    }

    //    定义子类型
    function Sub() {
        this.subPro = 'Sub property'
    }
    Sub.prototype = new Supper()
    Sub.prototype.constructor = Sub
    let sub = new Sub();
    console.log('sub.supPro ', sub.supPro);
</script>
<script>
    function Parent() {
        this.name = 'parent';
        this.play = [1, 2, 3]
    }

    function Child() {
        this.type = 'child';
    }

    Child.prototype = new Parent();
    Child.prototype.constructor = Child

    //实例化两个对象
    let s1 = new Child();
    let s2 = new Child();
    console.log(s1.play, s2.play) //[1, 2, 3]    [1, 2, 3]

    //修改其中一个的原型
    s1.play.push(4)
    console.log('s1.play ', s1.play)
    console.log('s2.play ', s2.play)
</script>

在这里插入图片描述
当我们改变S1的属性时,另外一个实例也发生了改变,这是因为这两个实例使用的是同一个原型对象,他们的内存空间是共享的

2 构造函数继承(bad)

<script>
    function Parent() {
        this.name = 'Parent'
        this.play = [1, 2, 3]
    }

    Parent.prototype.getName = function () {
        return this.name
    }

    //定义构造函数
    function Child() {
        Parent.call(this);
        this.type = 'Child'
    }

    let child = new Child()
    let _child = new Child()

    child.play.push(100)

    console.log('child ', child)
    console.log('_child ', _child)

    child.getName() //报错
</script>

在这里插入图片描述
相比第一种原型链继承方式,父类的引用属性不会被共享,但他优化了第一种继承方式的弊端
只能继承父类的实例属性和方法,不能继承其原型属性或方法

3 组合继承

前面我们讲到两种继承方式,各有优缺点.组合继承则是将这两种方式结合起来: 原型链继承+构造函数继承

<script>
    function Parent() {
        this.name = 'Parent';
        this.play = [1, 2, 3];
    }

    Parent.prototype.getName = function () {
        return this.name
    }

    function Child() {
        Parent.call(this);
        this.type = 'Child'
    }

    Child.prototype = new Parent();
    Child.prototype.constructor = Child;

    let s1 = new Child();
    let s2 = new Child();
    console.log('s1.play ', s1.play)
    console.log('s2.play ', s2.play)

    s1.play.push(4)
    console.log('s1.play ', s1.play)
    console.log('s2.play ', s2.play)
    
    console.log('s1.getName() ', s1.getName())
    console.log('s2.getName() ', s2.getName())
</script>

在这里插入图片描述
这种方式看起来没什么问题,但实际上 Parent 执行了两次,造成了多构造一次的性能开销。

4 super

我们知道, this关键字总是指向函数所在的当前对象 , ES6 又新增了另一个类似的关键字 [ super ], 指向当前对象的原型对象.

<script>
    const proto = {foo: 'hello'};

    const obj = {
        foo: 'world',
        find() {
            return super.foo;
        },
        _find() {
            return this.foo;
        }
    };
    Object.setPrototypeOf(obj, proto);
    console.log(obj.__proto__);
    console.log('obj.find() ', obj.find());
    console.log('obj._find() ', obj._find());
</script>

在这里插入图片描述
上面代码中, 对象obj.find()方法之中, 通过super.foo引用了原型对象proto的foo属性.

注意, super关键字表示原型对象时, 只能用在对象的方法之中, 用在其他地方都会报错.

<script>
    // 报错
    const obj = {
        foo: super.foo
    }
    // 报错
    const obj = {
        foo: () => super.foo
    }
    // 报错
    const obj = {
        foo: function () {
            return super.foo
        }
    }
</script>

上面三种super的用法都会报错, 因为对于 JavaScript 引擎来说, 这里的super都没有用在对象的方法之中. 第一种写法是super用在属性里面; 第二种和第三种写法是super用在一个函数里面, 然后赋值给foo属性. 目前, 只有对象方法的简写法可以让 JavaScript 引擎确认, 定义的是对象的方法.

<script>
    const proto = {
        x: 'hello',
        foo() {
            console.log('proto ', this.x);
        },
    };
    const obj = {
        x: 'world',
        foo() {
            console.log('obj ')
            super.foo();
        }
    }
    Object.setPrototypeOf(obj, proto);
    obj.foo() // world
</script>

上面代码中, super.foo()指向原型对象protofoo()方法, 但是绑定的this却还是当前对象obj, 因此输出的就是world.

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

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

相关文章

如何实现外网访问内网ip?公网端口映射或内网映射来解决

本地搭建服务器应用&#xff0c;在局域网内可以访问&#xff0c;但在外网不能访问。如何实现外网访问内网ip&#xff1f;主要有两种方案&#xff1a;路由器端口映射和快解析内网映射。根据自己本地网络环境&#xff0c;结合是否有公网IP&#xff0c;是否有路由权限&#xff0c;…

0.4如何使用cmake来管理项目

如何使用cmake来管理项目 【opencv源码解析0.1】VS如何优雅的配置opencv环境 【opencv源码解析0.2】如何编译opencv库源码 【opencv源码解析0.3】调试opencv源码以及使用cmake来管理项目 前面几篇文章我们都是围绕Visual Studio 2019这个IDE来展开的&#xff0c;IDE为我们做了…

【OJ】小熊猫的肉质品

&#x1f4da;Description: 自从可爱的小熊猫来到浙商大后便再也不想吃那些膳食纤维了&#xff0c;比如&#xff1a;竹子。所以&#xff0c;骞哥&#xfeff;不得不帮助国宝寻找一些肉类来维持能量&#xff0c;使得小熊猫不至于饿死在全球某工商。但是&#xff0c;你知道的淘…

Spring Cloud Alibaba--seata微服务详解之分布式事务(三)

上篇讲述gateway的部署和使用&#xff0c;gateway统一管理和转发了HTTP请求&#xff0c;在互联网中大型项目一定存在复杂的业务关系&#xff0c;尤其在商城类软件中如淘宝、PDD等商城&#xff0c;尤其在秒杀场景中&#xff0c;并发量可以到达千万级别&#xff0c;此时数据库就会…

第五十六章 树状数组(一)

第五十六章 树状数组一、前缀和的缺陷二、树状数组1、作用2、算法分析3、算法实现&#xff08;1&#xff09;lowbits()&#xff08;2&#xff09;插入&#xff08;3&#xff09;查询三、例题1、问题题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1提示2、代码一、前缀和…

【SCL】1200应用项目: 四节传送带机械手模拟控制

使用SCL编写小应用:四节传送带模拟和机械手模拟控制 文章目录 目录 文章目录 前言 一、四节传送带模拟控制 1.控制要求 2.参考图 3.接线图和I/0分配 4.编写程序 1.逆序启动 2.顺序停止 3.故障输入 4.调试 5.完整代码 二、机械手控制 1.控制要求 2. 接线图和I/0分配 3.编写程序 …

JVM内存模型深度剖析与优化

1. Java语言的跨平台特性 2. JVM整体结构及内存模型 堆存放着对象信息每个线程都会分配一块属于自己的内存空间&#xff08;栈空间&#xff09; 每个方法都会分配一块内存空间&#xff08;栈桢&#xff09;&#xff0c;上图 compute()方法 和 main()方法 都会分配到各自的栈桢空…

git 学习笔记

Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件,可以敏捷高效地处理任何或小或大的项目。Git 与常用的版本控制工具 CVS, Subversion 等不同&#xff0c;它采用了分布式版本库的方式&#xff0c;不需要服务器端软件支持。 一、安装配置…

线性神经网络(sotfmax回归)

sotfmax回归定义网络架构softmax运算softmax回归实现&#xff08;MNIST数据集&#xff09;数据集的处理读取数据集查看形状数据可视化读取小批量整合所有组件神经网络的搭建加载数据集初始化模型参数定义softmax函数定义模型定义损失函数&#xff08;难点&#xff09;分类精度训…

有序表之跳表

文章目录1、前言2、跳表简介3、理解“跳表”4、用跳表查询到底有多快5、跳表是不是很浪费内存6、高效的动态插入和删除7、跳表索引动态更新8、跳表代码实现1、前言 在开始讲解跳表之前&#xff0c;先来说一说积压结构。 何为积压结构&#xff1f;就是当数据达到了一定程度&am…

【ROS2实践】Vmware17下安装ubuntu22.04和ros2-humble

一、简介 ROS2-foxy已经不再维护&#xff0c;ROS2-humble成为主角&#xff0c;因而该转变一下开发场景了。如何安装&#xff1f;官方文档没有错&#xff0c;然而&#xff0c;照着做却无法进行。实超中遇到的需要变通的地方&#xff0c;官网是不给你提供解决的&#xff0c;本文给…

宽刈幅干涉高度计SWOT(Surface Water and Ocean Topography)卫星进展(待完善)

以下信息搬运自SWOT官方网站等部分文献资料&#xff0c;如有侵权请联系&#xff1a;sunmingzhismz163.com 排版、参考文献、部分章节待完善 概况 2022年12月16日地表水与海洋地形卫星SWOT (Surface Water and Ocean Topography)在加利福尼亚州范登堡航天基地由SpaceX猎鹰9号(Sp…

mysql面试题(最全)

1. 数据库三大范式是什么&#xff1f; 什么是范式&#xff1f; 范式是数据库设计时遵循的一种规范&#xff0c;不同的规范要求遵循不同的范式。 最常用的三大范式 第一范式(1NF)&#xff1a;属性不可分割&#xff0c;即每个属性都是不可分割的原子项。(实体的属性即表中的列)…

ESXi主机CVE-2021-21972漏洞复现安全处置建议

一、漏洞简介 vSphere 是 VMware 推出的虚拟化平台套件&#xff0c;包含 ESXi、vCenter Server 等一系列的软件。其中 vCenter Server 为 ESXi 的控制中心&#xff0c;可从单一控制点统一管理数据中心的所有 vSphere 主机和虚拟机。 vSphere Client&#xff08;HTML5&#xf…

【博客624】MAC地址表、ARP表、路由表(RIB表)、转发表(FIB表)

MAC地址表、ARP表、路由表(RIB表/FIB表) MAC地址表 MAC地址表是交换机等网络设备记录MAC地址和端口的映射关系&#xff0c;代表了交换机从哪个端口学习到了某个MAC地址&#xff0c;交换机把这个信息记录下来&#xff0c;后续交换机需要转发数据的时候就可以根据报文的目的MAC地…

SpringBoot社区版专业版带你配置热部署

&#x1f49f;&#x1f49f;前言 ​ 友友们大家好&#xff0c;我是你们的小王同学&#x1f617;&#x1f617; 今天给大家打来的是 SpringBoot社区版专业版带你配置热部署 希望能给大家带来有用的知识 觉得小王写的不错的话麻烦动动小手 点赞&#x1f44d; 收藏⭐ 评论&#x1…

C++类基础(十七)

类的继承——补充知识 ● public 与 private 继承&#xff08;C Public, Protected and Private Inheritance&#xff09; 改变了类所继承的成员的访问权限 //公有继承 struct Base { public:int x; private:int y; protected:int z; }; struct Derive : public Base //公有继承…

【数据结构与算法】时间复杂度与空间复杂度

目录 一.前言 二.时间复杂度 1.概念 二.大O的渐进表示法 概念&#xff1a; 总结&#xff1a; 三.常见时间复杂度计算举例 例1 例2 例3 例4 例5.计算冒泡排序的时间复杂度 例6.二分算法的时间复杂度 例7.阶乘递归Fac的时间复杂度 例8.斐波那契递归的时间复杂度 …

【MyBatis】| MyBatis的注解式开发

目录 一&#xff1a;MyBatis的注解式开发 1. Insert注解 2. Delete注解 3. Update注解 4. Select注解 5. Results注解 一&#xff1a;MyBatis的注解式开发 MyBatis中也提供了注解式开发⽅式&#xff0c;采⽤注解可以减少Sql映射⽂件的配置。 当然&#xff0c;使⽤注…

推荐几款好用的数据库管理工具

本文主要介绍几款常用的数据库管理软件&#xff08;客户端&#xff09;&#xff0c;包括开源/免费的、商用收费的&#xff0c;其中有一些是专用于 MySQL 数据库的&#xff0c;例如 MySQL Workbench、phpMyAdmin&#xff0c;有一些是支持多种 SQL、NoSQL 数据库的&#xff0c;例…