Es6--对象的新增方法

一、Object.is() —比较两个值是否严格相等

  • es5中比较两个值是否相等,使用的是== 和 ===运算符
  • es6中使用Object.is() ,它用来比较两个值是否严格相等,与===运算符的行为基本一致。不同之处只有两个:一是+0不等于-0,二是NaN等于自身。
  • 检测的变量存在值类型和引用类型。
       console.log(Object.is('abc','abc'));//true
       console.log(Object.is({},{}));//false
       console.log(Object.is(+0,-0));//false
       console.log(Object.is(NaN,NaN));//true
  • 因为数组是引用类型,不会恒等。
  • 自己实现is()方法的内部原理。
       Object.defineProperty(Object,'is',{
           value:function(x,y){
               if(x === y)
               {
                   return true;
               }
               else{
                   return false;
               }
           }
       });
       console.log(Object.is({},{}));

二、Object.assign()—对象合并

  • Object.assign()方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。
  • Object.assign()方法的第一个参数是目标对象,后面的参数都是源对象。
  • 有3个参数;
  • 第一个参数是合并之后的目标
  • 第二个参数是合并对象之一
  • 第三个参数是合并对象之一
       let h1 = {a:1,b:2};
       let h2 = {a:2,c:3};
       console.log(Object.assign({},h1,h2));//{a: 2, b: 2, c: 3}
  • 该方法返回值是合并之后的对象
  • 合并规则:不同属性叠加,相同属性后面属性覆盖前面属性。
  • 注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
       let h1 = {a:1,b:2};
       let h2 = {a:2,c:3};
       let target = {};
       console.log(Object.assign(target,h1,h2));//{a: 2, b: 2, c: 3}
       console.log(target);//{a: 2, b: 2, c: 3}
  • 等价于$.extend()。
  • 如果只有一个参数,Object.assign()会直接返回该参数。
    const obj = {a: 1};
    console.log(Object.assign(obj));//{a: 1}
  • 如果该参数不是对象,则会先转成对象,然后返回。
    console.log(Object.assign(2));//Number {2}
    console.log(typeof Object.assign(2));//object
  • 由于undefined和null无法转成对象,所以如果它们作为参数,就会报错。
    console.log(Object.assign(undefined));//TypeError: Cannot convert undefined or null to object
    console.log(Object.assign(null));//TypeError: Cannot convert undefined or null to object
  • 如果非对象参数出现在源对象的位置(即非首参数),那么处理规则有所不同。首先,这些参数都会转成对象,如果无法转成对象,就会跳过。这意味着,如果undefined和null不在首参数,就不会报错。
    let obj = {a: 1};
    console.log(Object.assign(obj, undefined));//{a: 1}
    console.log(Object.assign(obj, null));//{a: 1}
  • 其他类型的值(即数值、字符串和布尔值)不在首参数,也不会报错。但是,除了字符串会以数组形式,拷贝入目标对象,其他值都不会产生效果。
    const a = 'abc';
    const b = true;
    const c = 10;
    const obj = Object.assign({}, a, b, c);
    console.log(obj);//{0: "a", 1: "b", 2: "c"}
  • 只有字符串合入目标对象(以字符数组的形式),数值和布尔值都会被忽略。这是因为只有字符串的包装对象,会产生可枚举属性。
  • Object.assign()拷贝的属性是有限制的,只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false)。
  • 属性名为 Symbol 值的属性,也会被Object.assign()拷贝。

1. 浅拷贝

  • Object.assign()方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。
       const obj1 = {a:{b:1}};
       const obj2 = Object.assign({},obj1);
       obj1.a.b = 2;
       console.log(obj2.a.b);//2
  • 为什么obj1.a.b的值改变了,obj2.a.b的值也随之改变了?
  • 这是因为Object.assign()方法实行的是浅拷贝,只拷贝了obj1外层的引用,而没有拷贝内层的引用。这个对象的任何变化,都会反映到目标对象上面。
       const obj1 = {a:1};
       const obj2 = Object.assign({},obj1);
       obj1.a = 2;
       console.log(obj2.a);//1

2. 同名属性的替换

  • 对于这种嵌套的对象,一旦遇到同名属性,Object.assign()的处理方法是替换,而不是添加。
       let o1 = {a:1,b:2,c:3};
       let o2 = {a:'abc',b:'def'};
       console.log(Object.assign(o1,o2));//{a: "abc", b: "def", c: 3}

3. 数组的处理

       let o3 = [1,2,3];
       let o4 = [4,5];
       console.log(Object.assign(o3,o4));//[4, 5, 3]
  • 数组的合并是按照索引合并的。

4. 取值函数的处理

  • Object.assign()只能进行值的复制,如果要复制的值是一个取值函数,那么将求值后再复制。
    const source = {
        get foo() { return 1 }
    };
    const target = {};
    console.log(Object.assign(target, source));//{foo: 1}

5. Object.assign()方法的应用

(1)给对象添加属性

       let work = {};
       console.log(Object.assign(work,{a:1,b:2}));//{a: 1, b: 2}

(2)给对象添加方法

  • 使用Object.assign()给原型对象上添加方法。
       Array.prototype.mySort = function(){
           mySort = function(){

           }
       }
       Object.assign(Array.prototype,{
           myPai:function(){

           }
       })
       console.log(Array.prototype);

在这里插入图片描述

(3)克隆对象

    function clone(origin) {
        return Object.assign({}, origin);
    }
    console.log(clone({a:1,b:2,c:3}));//{a: 1, b: 2, c: 3}
  • 采用这种方法克隆,只能克隆原始对象自身的值,不能克隆它继承的值。
    function clone(origin) {
        let originProto = Object.getPrototypeOf(origin);
        return Object.assign(Object.create(originProto), origin);
    }
    console.log(clone({a:1,b:2,c:3}));//{a: 1, b: 2, c: 3}

(4)合并多个对象

  • 将多个对象合并到某个对象。

三、Object.getOwnPropertyDescriptors()—返回某个对象属性的描述对象

  • ES5 的Object.getOwnPropertyDescriptor()方法会返回某个对象属性的描述对象(descriptor)。ES2017 引入了Object.getOwnPropertyDescriptors()方法,返回指定对象所有自身属性(非继承属性)的描述对象。
  • 该方法的引入目的,主要是为了解决Object.assign()无法正确拷贝get属性和set属性的问题。
    const obj={
        foo:123,
        get bar(){
            return 'abc'
        }
    };
    console.log(Object.getOwnPropertyDescriptors(obj));

在这里插入图片描述

  • 上面代码中,Object.getOwnPropertyDescriptors()方法返回一个对象,所有原对象的属性名都是该对象的属性名,对应的属性值就是该属性的描述对象。

自己实现getOwnPropertyDescriptors()方法

    function getOwnPropertyDescriptors(obj) {
        const result = {};
        for (let key of Reflect.ownKeys(obj)) {
            result[key] = Object.getOwnPropertyDescriptor(obj, key);
        }
        return result;
    }
    console.log(getOwnPropertyDescriptors({
        foo: 123, get bar() {
            return 'abc'
        }
    }));

四、__proto__属性,Object.setPrototypeOf(),Object.getPrototypeOf()

1. __proto__属性—读取或设置当前对象的原型对象

  • __proto__属性(前后各两个下划线),用来读取或设置当前对象的原型对象(prototype)。
    //es5 的写法
    const obj = {
        method: function() {}
    };
    obj.__proto__ = someOtherObj;
    //es6 的写法
    var obj = Object.create(someOtherObj);
    obj.method = function(){};
  • __proto__调用的是Object.prototype. __proto __
  • 如果一个对象本身部署了__proto__属性,该属性的值就是对象的原型。

2. Object.setPrototypeOf()—设置一个对象的原型对象

  • Object.setPrototypeOf方法的作用与__proto__相同,用来设置一个对象的原型对象(prototype),返回参数对象本身。它是 ES6 正式推荐的设置原型对象的方法。
    let obj={x:10};
    Object.setPrototypeOf(obj,proto);
    proto.y=20;
    proto.z=40;
    console.log(obj.x);//10
    console.log(obj.y);//20
    console.log(obj.z);//40
  • 上面代码将proto对象设为obj对象的原型,所以从obj对象可以读取proto对象的属性。
    let proto={};
    let a=1;
    Object.setPrototypeOf(a,proto);
    proto.y=20;
    proto.z=40;
    console.log(a.x);//undefined
    console.log(a.y);//undefined
    console.log(a.z);//undefined
  • 如果第一个参数不是对象,会自动转为对象。但是由于返回的还是第一个参数,所以这个操作不会产生任何效果。
    console.log(Object.setPrototypeOf(1, {}));//1
    console.log(Object.setPrototypeOf('abc', {}));//abc
    console.log(Object.setPrototypeOf(true, {}));//true
  • 由于undefined和null无法转为对象,所以如果第一个参数是undefined或null,就会报错。
    console.log(Object.setPrototypeOf(undefined, {}));//TypeError: Object.setPrototypeOf called on null or undefined
    console.log(Object.setPrototypeOf(null, {}));//TypeError: Object.setPrototypeOf called on null or undefined

3. Object.getPrototypeOf()—读取一个对象的原型对象

  • 该方法与Object.setPrototypeOf方法配套,用于读取一个对象的原型对象。
    function Rect(){

    }
    const  rec=new Rect();
    console.log(Object.getPrototypeOf(rec)===Rect.prototype);//true
    console.log(Object.setPrototypeOf(rec, Object.prototype));
    console.log(Object.getPrototypeOf(rec)===Rect.prototype);//false
  • 如果参数不是对象,会被自动转为对象。
    //等同于Object.getPrototypeOf(Number(1))
    console.log(Object.getPrototypeOf(1));
    console.log(typeof Object.getPrototypeOf(1));//object
    //等同于Object.getPrototypeOf(String('foo'))
    console.log(Object.getPrototypeOf('foo'));
    console.log(typeof Object.getPrototypeOf('foo'));//object
    //等同于Object.getPrototypeOf(Boolean(true))
    console.log(Object.getPrototypeOf(true));
    console.log(typeof Object.getPrototypeOf(true));//object
    console.log(Object.getPrototypeOf(1) === Number.prototype);//true
    console.log(Object.getPrototypeOf('foo') === String.prototype);//true
    console.log(Object.getPrototypeOf(true) === Boolean.prototype);//true

在这里插入图片描述

  • 如果参数是undefined或null,它们无法转为对象,所以会报错。

五、Object.keys(),Object.values(),Object.entries()

  • Object.keys()------获取所有的key
  • Object.values()—获取所有的值
  • Object.entries()—获取键值

1. Object.keys()----遍历键名

  • ES5 引入了Object.keys方法,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名。
    //返回的是key的集合
    console.log(Object.keys({a:1,b:2,c:3}));//(3) ["a", "b", "c"]

2. Object.values()—遍历键值

  • Object.values方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
  • Object.values会过滤属性名为 Symbol 值的属性。
  • 如果Object.values方法的参数是一个字符串,会返回各个字符组成的一个数组。
  • 如果参数不是对象,Object.values会先将其转为对象。由于数值和布尔值的包装对象,都不会为实例添加非继承的属性。所以,Object.values会返回空数组。
    //返回值的集合
    console.log(Object.values({a:1,b:2,c:3}));//(3) [1, 2, 3]
    //返回顺序:属性名为数值的属性,是按照数值大小,从小到大遍历的
    const obj={100:'a',2:'b',7:'c'};
    console.log(Object.values(obj));//(3) ["b", "c", "a"]
    //Object.values只返回对象自身的可遍历属性。
    const obj1=Object.create({},{p:{value:42}});
    console.log(Object.values(obj1));//[]
    const obj2=Object.create({},{p:{value:42,enumerable:true}});
    console.log(Object.values(obj2));//[42]
    //Object.values会过滤属性名为Symbol值的属性
    console.log(Object.values({[Symbol()]:123,foo:'abc'}));//["abc"]
    //如果Object.values方法的参数是一个字符串,会返回各个字符组成的一个数组
    //字符串会先转成一个类似数组的对象。字符串的每个字符,就是该对象的一个属性。
    //因此,Object.values返回每个属性的键值,就是各个字符组成的一个数组。
    console.log(Object.values('foo'));//(3) ["f", "o", "o"]
    //如果参数不是对象,Object.values会先将其转为对象。
    //由于数值和布尔值的包装对象,都不会为实例添加非继承的属性。所以,Object.values会返回空数组。
    console.log(Object.values(42));//[]
    console.log(Object.values(true));//[]

3. Object.entries()—遍历键值对

  • Object.entries()方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。
  • 除了返回值不一样,该方法的行为与Object.values基本一致。
  • Object.entries方法的另一个用处是,将对象转为真正的Map结构。
    //返回的是key:value的二维数组
    console.log(Object.entries({a:1,b:2,c:3}));//[Array(2), Array(2), Array(2)]
    //如果原对象的属性名是一个 Symbol 值,该属性会被忽略
    console.log(Object.entries({[Symbol()]:123,foo:'abc'}));
    //Object.entries的基本用途是遍历对象的属性
    let obj={one:1,two:2};
    for(let [k,v] of Object.entries(obj)){
        console.log(`${JSON.stringify(k)}:${JSON.stringify(v)}`);
    }
    //Object.entries方法的另一个用处是,将对象转为真正的Map结构。
    const obj1={foo:'bar',baz:42};
    const map=new Map(Object.entries(obj1));
    console.log(map);

在这里插入图片描述

自己实现Object.entries方法

    function entries(obj){
        let arr=[];
        for(let key of Object.keys(obj)){
            arr.push([key,obj[key]]);
        }
        return arr;
    }

4. for…of遍历

    //遍历
    let obj={a:1,b:2,c:3};
    for(let key of Object.keys(obj)){
        console.log(key);
    }
    for(let value of Object.values(obj)){
        console.log(value);
    }
    for(let [key,value] of Object.entries(obj)){
        console.log([key, value]);
    }

在这里插入图片描述

六、Object.fromEntries()—将一个键值对数组转为对象

  • Object.fromEntries()方法是Object.entries()的逆操作,用于将一个键值对数组转为对象。
    console.log(Object.fromEntries([
        ['foo', 'bar'],
        ['baz', 42]
    ]));//{foo: "bar", baz: 42}
  • 该方法的主要目的,是将键值对的数据结构还原为对象,因此特别适合将 Map 结构转为对象。
    const entries=new Map([
        ['foo', 'bar'],
        ['baz', 42]
    ]);
    console.log(Object.fromEntries(entries));//{foo: "bar", baz: 42}
    const map=new Map().set('foo', true).set('bar', false);
    console.log(Object.fromEntries(map));//{foo: true, bar: false}
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南初️

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值