ES6 - 对象新增的一些常用方法

文章目录

    • 1,Object.is()
    • 2,Object.asign()
    • 3,Object.getOwnPropertyDescriptors()
    • 4,Object.setPrototypeOf()和getPrototypeOf()
    • 5,Object.keys()、values() 和 entries()
    • 6,Object.fromEntries()
    • 7,Object.hasOwn()

1,Object.is()

再ES5中 比较两个值是否相等,只有两个运算符:相等运算符(==)和严格相等运算符(===
但它们都有缺点,前者会自动转换数据类型,后者的NaN不等于自身,以及+0等于-0

先说它们两个的比较过程:

双等号==

(1)如果两个值类型相同,再进行三个等号(===)的比较

(2)如果两个值类型不同,也有可能相等,需根据以下规则进行类型转换在比较:
 
    1)如果一个是null,一个是undefined,那么相等
    2)如果一个是字符串,一个是数值,把字符串转换成数值之后再进行比较

三等号===:

(1)如果类型不同,就一定不相等

(2)如果两个都是数值,并且是同一个值,那么相等;如果其中至少一个是NaN,那么不相等。

(3)如果两个都是字符串,每个位置的字符都一样,那么相等,否则不相等。

(4)如果两个值都是true,或是false,那么相等

(5)如果两个值都引用同一个对象或是函数,那么相等,否则不相等

(6)如果两个值都是null,或是undefined,那么相等

ES6 提出“Same-value equality”(同值相等)算法,用来解决这个问题。Object.is就是部署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。

Object.is('123', '123')
// true
Object.is({}, {})
// false
Object.is([], [])
// false

Object.is() 判断两个值是否相同。如果下列任何一项成立,则两个值相同:

  • 两个值都是undefined
  • 两个值都是 null
  • 两个值都是 true 或者都是 false
  • 两个值是由相同个数的字符按照相同的顺序组成的字符串
  • 两个值指向同一个对象
  • 两个值都是数字并且
    • 都是正零 +0
    • 都是负零 -0
    • 都是 NaN
    • 都是除零和 NaN 外的其它同一个数字

如下的案例:

      console.log(111 == '111');// true 先转数子再比较是否一样
      
      // 1,判断 undefined 
      console.log(undefined === undefined);  // true
      console.log(Object.is(undefined, undefined)); // true

      // 2,判断 null 
      console.log(null === null); // true
      console.log(Object.is(null,null)); // true

      // 3,判断空数组[]
      console.log([] === []); // false
      console.log(Object.is([],[])); // false

      // 4,需要特别注意下 +0和-0
      console.log(+0 === -0); // true 显然是判断失误了
      console.log(Object.is(+0, -0)); //false

      // 5,判断NaN
      console.log(NaN === NaN); // false  显然也是判断失误了
      console.log(Object.is(NaN,NaN)); // true

可以看出,使用Object.is()方法会有更高的准确度。


2,Object.asign()

  • 基本用法

Object.assign()方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。

      // 目标对象 也可以是一个空对象
      const target = { name: 'Eula' };
      // 源对象 可以有多个
      const source1 = { age: 18 };
      const source2 = { friend: 'Amber' };

      Object.assign(target, source1, source2);
      console.log("target:",target); //{name: 'Eula', age: 18, friend: 'Amber'}

Object.assign()方法的第一个参数是目标对象,后面的参数都是源对象。

注意 :如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性,如下:

      // 目标对象 
      const target = { name: 'Eula' }; // 这个会被覆盖掉
      // 源对象 
      const source1 = { age: 18 };
      const source2 = { name: 'Amber' };

      Object.assign(target, source1, source2);
      console.log("target:",target); //{name: 'Amber', age: 18}

Object.assign()拷贝的属性是有限制的,只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false)。

     let copyA = Object.assign(
        { name: "Eula" },
        Object.defineProperty({}, "age", {
          enumerable: false, // 不可枚举
          value: 18 // 为此属性添加值 18 
        })
      );
      
      console.log("copyA:",copyA);//{ name: "Eula" }

上面代码中,Object.assign()要拷贝的对象只有一个不可枚举属性age,这个属性并没有被拷贝进去。如果把enumerable 改为true,就可以成功拷贝;

  • assign()方法 注意事项:

(1)浅拷贝

Object.assign()方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。

      const obj1 = {my:{ name: "Eula"} };
      const obj2 = Object.assign({}, obj1);
      // 改变源对象的属性
      obj1.my.name = "Amber"
      console.log(obj2); //{my: {name: 'Amber'}} 

Object.assign()拷贝得到的是这个对象的引用。这个对象的任何变化,都会反映到目标对象上面。

(2)同名属性的替换

对于这种嵌套的对象,一旦遇到同名属性,Object.assign()的处理方法是替换,而不是添加。

      const target = { my: { name: "Eula", age: 18 } };
      const source = { my: { name: "Amber" } };
      let res = Object.assign(target, source);
      console.log(res);// {my: {name: 'Amber'}}

一些函数库提供Object.assign()的定制版本(比如 Lodash 的_.defaultsDeep()方法),可以得到深拷贝的合并。


3,Object.getOwnPropertyDescriptors()

该方法返回指定对象所有自身属性(非继承属性)的描述对象;如下:

     const obj1 = {
        name: "Eula",
        fun: function () {
          return "优菈";
        }
      };
      const  Descriptors = Object.getOwnPropertyDescriptors(obj1)
      console.log("Descriptors:",Descriptors);

打印结果如下:
在这里插入图片描述


4,Object.setPrototypeOf()和getPrototypeOf()

  • setPrototypeOf()

Object.setPrototypeOf方法用来设置一个对象的原型对象;下面案例是给obj原型上添加一个属性 age:

      let obj1 = { name: "Eula" };
      let obj2 = { age: 18 };
      // 下面是给obj1添加一个属性 name
      Object.setPrototypeOf(obj1, obj2);
      console.log(obj1.age); //18
  • getPrototypeOf()

该方法与Object.setPrototypeOf方法配套,用于读取一个对象的原型对象,下面是读取obj1 新增的原型属性:

      let obj1 = { name: "Eula" };
      let obj2 = { age: 18 };
      // 下面是给obj1添加一个属性 name
      Object.setPrototypeOf(obj1, obj2);
      
      // 获取里面原型对象
      console.log(Object.getPrototypeOf(obj1)); //  { age: 18 }

5,Object.keys()、values() 和 entries()

(1) Object.keys()

返回自身的(不含继承的)所有可遍历(enumerable)属性的键名的数组。

      const ys = { KamisatoAyaka: '神里绫华', ShenliLingren: '神里绫人' };
      let ysKeys = Object.keys(ys)
      console.log(ysKeys); //  ['KamisatoAyaka', 'ShenliLingren'] 注意:只返回了对象每一项的键名

(2)Object.values()

返回自身的(不含继承的)所有可遍历(enumerable)属性的键值的数组。

      const ys = { KamisatoAyaka: '神里绫华', ShenliLingren: '神里绫人' };
      let ysvalues = Object.values(ys)
      console.log(ysvalues); // ['神里绫华', '神里绫人'] 注意:只返回了对象每一项的键值

(3)Object.entries()

返回一个对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对的数组。
注意:entries方法同时返回了此对象的键值对, 并用一个数组包装。

      const ys = { KamisatoAyaka: "神里绫华", ShenliLingren: "神里绫人" };
      let ysentries = Object.entries(ys);
      console.log(ysentries);
      // 同时返回了键值对 并用一个数组包装
      //  ['KamisatoAyaka', '神里绫华']
      //  ['ShenliLingren', '神里绫人']

以下是配合for of 循环使用:

1,keys()是对键名的遍历

      let obj = {
        Amber: "安柏",
        Eula: "优菈",
        KamisatoAyaka: "神里绫华"
      };
	  // for of不支持遍历普通对象,可通过与Object.keys()搭配使用遍历
      for (let key of Object.keys(obj)) {
        console.log(key); // Amber,Eula,KamisatoAyaka  拿到的都是对象的键名
      }
      console.log(Object.keys(obj)); //(3) ['Amber', 'Eula', 'KamisatoAyaka']

2,values()是对键值的遍历

      let obj = {
        Amber: "安柏",
        Eula: "优菈",
        KamisatoAyaka: "神里绫华"
      };
      for (let key of Object.values(obj)) {
        console.log(key); // 安柏,优菈,神里绫华  拿到的都是对象的值
      }
      console.log(Object.values(obj)); //(3) ['安柏', '优菈', '神里绫华']

3,entries()是对键值对的遍历

      let obj = {
        Amber: "安柏",
        Eula: "优菈",
        KamisatoAyaka: "神里绫华"
      };
      for (let key of Object.entries(obj)) {
        console.log(key);
        // ['Amber', '安柏']
        // ['Eula', '优菈']
        // ['KamisatoAyaka', '神里绫华']
      }

      console.log(Object.entries(obj));
      // 会以一个数组重新包装起来
      // [
      //   ["Amber", "安柏"],
      //   ["Eula", "优菈"],
      //   ["KamisatoAyaka", "神里绫华"]
      // ];

6,Object.fromEntries()

Object.fromEntries()方法是Object.entries()的逆操作,用于将一个键值对数组转为对象。

Object.fromEntries([
  ['foo', 'bar'],
  ['baz', 42]
])
// { foo: "bar", baz: 42 }

该方法的主要目的,是将键值对的数据结构还原为对象,因此特别适合将 Map 结构转为对象。

// 例一
const entries = new Map([
  ['foo', 'bar'],
  ['baz', 42]
]);

Object.fromEntries(entries)
// { foo: "bar", baz: 42 }

// 例二
const map = new Map().set('foo', true).set('bar', false);
Object.fromEntries(map)
// { foo: true, bar: false }

该方法的一个用处是配合URLSearchParams对象,将查询字符串转为对象。

Object.fromEntries(new URLSearchParams('foo=bar&baz=qux'))
// { foo: "bar", baz: "qux" }

7,Object.hasOwn()

Object.hasOwn() 时用来判断是否为自身的属性。

JavaScript 对象的属性分成两种:自身的属性和继承的属性。对象实例有一个hasOwnProperty()方法,也可以判断某个属性是否为原生属性。

Object.hasOwn()可以接受两个参数,第一个是所要判断的对象,第二个是属性名:

const foo = Object.create({ a: 123 });
foo.b = 456;

Object.hasOwn(foo, 'a') // false
Object.hasOwn(foo, 'b') // true

上面示例中,对象foo的属性a是继承属性,属性b是原生属性。Object.hasOwn()对属性a返回false,对属性b返回true

Object.hasOwn()的一个好处是,对于不继承Object.prototype的对象不会报错,而hasOwnProperty()是会报错的。

const obj = Object.create(null);

obj.hasOwnProperty('foo') // 报错
Object.hasOwn(obj, 'foo') // false

上面示例中,Object.create(null)返回的对象obj是没有原型的,不继承任何属性,这导致调用obj.hasOwnProperty()会报错,但是Object.hasOwn()就能正常处理这种情况。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【零基础??天速成 Java】Day2 - 初识面向对象

目录 前言 1. 可变参数的使用 2. 构造器 3. 包 1、包的创建 2、包的使用 3、包的命名规范 4、常用的包 5. 访问修饰符 6. 继承 7. super 关键字 8. 方法重写 Override 写在最后: 前言 我的 java 基础学习,跟的是韩顺平的 java 课程~ 本篇…

【腾讯云Cloud Studio实战训练营】React 快速构建点餐页面

前言: Cloud Studio是一个在线的云集成开发环境(IDE),可以让开发人员在浏览器中轻松地开发、测试、调试和部署应用程序。它提供了基于云的计算资源和工具,例如代码编辑器、编译器、调试器、版本控制系统和项目管理工具…

Spring Boot2.xx开启监控 Actuator

spring boot actuator介绍 Spring Boot包含许多其他功能,可帮助您在将应用程序推送到生产环境时监视和管理应用程序。 您可以选择使用HTTP端点或JMX来管理和监视应用程序。 审核,运行状况和指标收集也可以自动应用于您的应用程序。 总之Spring Boot Ac…

8月8日上课内容 研究nginx组件rewrite

location 匹配uri location 匹配的规则和优先级。(重点,面试会问,必须理解和掌握) nginx常用的变量,这个要求掌握 rewrite:重定向功能。有需要掌握,有需要理解的。 location匹配:…

用Vue实现页面访问拦截

(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 页面访问拦截 1.创建axios实例 2.添加拦截器 3.全局前置守卫 可选的第三个参数 next 总结&#xff1a…

状态模式(C++)

定义 允许一个对象在其内部状态改变时改变它的行为。从而使对象看起来似乎修改了其行为。 应用场景 在软件构建过程中,某些对象的状态如果改变,其行为也会随之,而发生变化,比如文档处于只读状态,其支持的行为和读写…

使用 Python 和 Flask 构建简单的 Restful API 第 1 部分

一、说明 我将把这个系列分成 3 或 4 篇文章。在本系列的最后,您将了解使用flask构建 restful API 是多么容易。在本文中,我们将设置环境并创建将显示“Hello World”的终结点。 我假设你的电脑上安装了python 2.7和pip。我已经在python 2.7上测试了本文…

无涯教程-Perl - fcntl函数

描述 该函数是系统fcntl()函数的Perl版本。使用FILEHANDLE上的SCALAR执行FUNCTION指定的功能。 SCALAR包含函数要使用的值,或者是任何返回信息的位置。 语法 以下是此函数的简单语法- fcntl FILEHANDLE, FUNCTION, SCALAR返回值 该函数返回0,但如果fcntl()的返回值为0,则返…

【Go语言】Golang保姆级入门教程 Go初学者chapter2

【Go语言】变量 VSCode插件 setting的首选项 一个程序就是一个世界 变量是程序的基本组成单位 变量的使用步骤 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zuxG8imp-1691479164956)(https://cdn.staticaly.com/gh/hudiework/imgmain/image-20…

CAD随机球体颗粒过渡区3D插件

插件介绍 CAD随机球体颗粒&过渡区3D插件可用于在AutoCAD软件内生成随机分布的球体及球体外侧过渡区部件,适用于科研绘图、有限元建模如混凝土细观、颗粒增强复合材料、随机三维骨料及过渡区等方面的应用。 插件可指定的参数有模型的长、宽、高;球…

< JavaScript小技巧:如何优雅的用【一行代码 】实现Js中的常用功能 >

文章目录 💬 前言👉 数组相关① 随机打乱数组顺序② 借助 new Set()对数组去重 / 对象数组根据唯一值去重③ 查找数组中 【 最值 】 出现的索引 👉 Web浏览器相关① 重新加载当前页面,相当于 Ctrl R② 滚动…

解决VScode远程服务器时opencv和matplotlib无法直接显示图像的问题

解决VScode远程服务器时opencv和matplotlib无法直接显示图像的问题 1、本方案默认本地已经安装了VScode与MobaXterm2、在服务器端3、在本地端安装MobaXterm4、测试5、opencv显示测试(测试过程中需保持MobaXterm开启的状态)6、 matplotlib显示测试&#x…

VSCode Remote-SSH (Windows)

1. VSCode 安装 VSCode 2. 安装扩展 Remote SSH Getting started Follow the step-by-step tutorial or if you have a simple SSH host setup, connect to it as follows: Press F1 and run the Remote-SSH: Open SSH Host… command.Enter your user and host/IP in the …

qemu 虚拟化

一、介绍QEMU Qemu是种非常古老的虚拟化技术,用于虚拟化系统组件并在其上运行多种CPU架构的程序或操作系统。 借助KVM,Qemu可以通过使用基于硬件的虚拟化来获得超快的计算速度。QEMU充当硬件供应商,KVM是CPU。KVM驻留在Linux内核中&#xff0…

Linux下的环境变量

目录 一、环境变量是什么?二、常见的环境变量三、查看环境变量的方法四、和环境变量相关的命令五、命令行参数五、环境变量通常是具有全局属性的 一、环境变量是什么? 环境变量通俗来说就是一种存储系统和应用程序运行需要的配置信息的方式。可以把环境…

Mr. Cappuccino的第57杯咖啡——简单手写Mybatis大致原理

简单手写Mybatis大致原理 大致原理项目结构项目代码代码测试 大致原理 底层基于JDK动态代理技术实现 项目结构 项目代码 pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns…

Flutter 自定义view

带进度动画的圆环。没gif&#xff0c;效果大家自行脑补。 继承CustomPainter&#xff0c;paint()方法中拿到canvas&#xff0c;绘制API和android差不多。 import package:flutter/material.dart;class ProgressRingPainter extends CustomPainter {double strokeWidth 20;Col…

整数规划——第三章 全单模矩阵

整数规划——第三章 全单模矩阵 若线性规划问题的约束矩阵为全单模矩阵&#xff0c;则该问题可行域的顶点都是整数点&#xff0c;从而线性规划与整数规划的最优解相同。 3.1 全单模性与最优性 考虑线性整数规划问题&#xff1a; (IP) min ⁡ c T x , s . t . A x ≤ b , x …

MATLAB的设置路径

在主页下的 或者在命令行输入path&#xff0c;命令行会出现所有路径 必须要将某些函数.m文件以及一些类文件包含在路径当中&#xff0c;否则在脚本代码中输入代码时&#xff0c;不会有代码提示

LeetCode96. 不同的二叉搜索树

96. 不同的二叉搜索树 文章目录 [96. 不同的二叉搜索树](https://leetcode.cn/problems/unique-binary-search-trees/)一、题目二、题解 一、题目 给你一个整数 n &#xff0c;求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种&#xff1f;返回满足题意的…