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

文章目录

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就是部署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。

js 复制代码
Object.is('123', '123')
// true
Object.is({}, {})
// false
Object.is([], [])
// false

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

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

如下的案例:

javascript 复制代码
      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)。

js 复制代码
      // 目标对象 也可以是一个空对象
      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()方法的第一个参数是目标对象,后面的参数都是源对象。

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

js 复制代码
      // 目标对象 
      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)。

js 复制代码
     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()方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。

javascript 复制代码
      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()的处理方法是替换,而不是添加。

javascript 复制代码
      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()

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

javascript 复制代码
     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:

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

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

javascript 复制代码
      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)属性的键名的数组。

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

(2)Object.values()

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

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

(3)Object.entries()

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

注意:entries方法同时返回了此对象的键值对, 并用一个数组包装。

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

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

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

js 复制代码
      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()是对键值的遍历

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

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

js 复制代码
      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()的逆操作,用于将一个键值对数组转为对象。

javascript 复制代码
Object.fromEntries([
  ['foo', 'bar'],
  ['baz', 42]
])
// { foo: "bar", baz: 42 }

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

javascript 复制代码
// 例一
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对象,将查询字符串转为对象。

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

7,Object.hasOwn()

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

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

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

javascript 复制代码
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()是会报错的。

javascript 复制代码
const obj = Object.create(null);

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

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

相关推荐
编程猪猪侠22 分钟前
Tailwind CSS 自定义工具类与主题配置指南
前端·css
qhd吴飞26 分钟前
mybatis 差异更新法
java·前端·mybatis
YGY Webgis糕手之路1 小时前
OpenLayers 快速入门(九)Extent 介绍
前端·经验分享·笔记·vue·web
患得患失9491 小时前
【前端】【vueDevTools】使用 vueDevTools 插件并修改默认打开编辑器
前端·编辑器
ReturnTrue8681 小时前
Vue路由状态持久化方案,优雅实现记住表单历史搜索记录!
前端·vue.js
UncleKyrie1 小时前
一个浏览器插件帮你查看Figma设计稿代码图片和转码
前端
遂心_1 小时前
深入解析前后端分离中的 /api 设计:从路由到代理的完整指南
前端·javascript·api
你听得到111 小时前
Flutter - 手搓一个日历组件,集成单日选择、日期范围选择、国际化、农历和节气显示
前端·flutter·架构
风清云淡_A1 小时前
【REACT18.x】CRA+TS+ANTD5.X封装自定义的hooks复用业务功能
前端·react.js
@大迁世界1 小时前
第7章 React性能优化核心
前端·javascript·react.js·性能优化·前端框架