带你认识不一样的对象,Object中追加属性以及assign、isPrototypeOf等大多对象方法以及深复制的使用

308 阅读6分钟

对象

原型链 obj是最底层的

var obj = {a:1};
console.log(obj)//在打印obj时obj下面会有一个proto属性,这个东西成为原型链。
console.log(obj.__proto__)//也可以使用obj.__proto__来直接打印
class Box{
        constructor(){

        }
        aaa(){

        }
        bbb(){

        }
 }//创建一个类
 var b = new Box();//创建一个实例化对象
 b.ccc=function(){//给实例化对象添加一个方法ccc
 
  }
  console.log(b)
//此时b中的只有ccc一个方法而aaa和bbb都在实例化对象原行b的原型链上 可以使用b.aaa来直接调用原型链上的方法
class Ball extends Box{
    constructor(){
        super()
    }
    ccc(){

    }
}//创建一个Ball类继承Box的方法
var b = new  Ball();
console.log(b)//此时b对象上的原型中就多了一个Box类 当继承的类型越来越多就会形成一条原型链  继承的类或方法存在于原型链中

所以万物皆对象,任何东西最底层的都是对象。

在对象中有三种创建方法。

var obj = {a:1}//字面量创建
var obj = new Object()//构造函数创建
var obj = Object.create()//以原型创建
//对象中的key必须是String或者Symbol类型,如果不是就会隐式转换为String类型
var o={a:1};
obj[o]=10;
console.log(obj[{b:3}]);//结果为10 对象会自动转化为字符串object
var arr=[0];
bj[arr]=100;
console.log(obj[0])//结果为100 数组转化为字符串会用逗号分开每一个值

重点说明一下第三种创建,前面两种没啥说的

var o = {a:1};
var o1 = Object.create(o)//以o为原型创建o1,此时在o1中就会有o对象这个原型
console.log(o1.__proto__===o)//true他们就是一样的 引用地址是相同的
//所以不能直接改变原型o中的数据这样会导致所有以o为原型的对象中的数据都发生改变
console.log(o1.a)//此时o1中没有a属性 所以在他的原型上查找 所以返回为1
o1.a=10;
consloe.log(o1.a)//当o1中具有a属性时 先返回o1上的属性值
 var obj={
                a:1,
                b:100,
                c:this.b,
            // 在对象的属性下使用this,this将指向对象外的this指向
     }//因为在你调用this时你这个obj还没有创建完成,所以他就会指向外部的this。
 console.log(obj.c)为undefined

当设置对象属性时,直接设置的时对象的自身属性

如果获取时,首先查看对象有没有这个名称的对象属性,如果有则直接返回,如果没有向下查找紧邻的原型链中的属性是否具有该属性名,查找到距离该对象最近的原型链中的属性名后返回其值。

对象的assign方法

var o = {a:1,b:2};
var o1 = Object.assign({},o)

原理就是创建一个新对象,并且将o上的属性复制到这个新对象上,然后返回这个对象。

不过这种方法复制对象时是浅复制,仅把第一层的属性复制到新对象上,如果第一层的属性值是引用类型,则会把引用地址赋值给新对象上。

Object.assign()将一个或者多个对象种可枚举属性赋值到第一个参数对象种,如果后面的对象属性与前面的对象属性相同时,则会覆盖前面的对象属性。

var o1={a:1,b:2,c:3};
var o2={d:4,e:5,f:6};
var o3={a:7,e:8,c:9};
Object.assign(o,o1,o2,o3);

原对象种增加复制的属性,引用地址不变;

var o1={a:1,b:2,c:3};
var o2={d:4,e:5,f:6};
var o3={a:7,e:8,c:9};
var o4={...o1,...o2,...o3}//相当于将o1,o2,o3所有属性解构产生新对象赋值给了o4;

对象的属性创建

使用Object.defineProperty()

参数类型为:对象,属性名,该属性的描述对象

var obj = {};
Object.defineProperty(obj,'a',{
     configurable:true,//该属性是否可以删除
     enumerable:true,//该属性是否可以枚枚举
     writable:true,//该属性是否可写(不是只读)
     value:10//该属性的值
})
var obj = {};
Object.defineProperty(obj,'a',{
     configurable:falsevalue:10//该属性的值
})
delete obj.a//此时无法删除该属性
var obj = {};
Object.defineProperty(obj,'a',{
        configurable:true,
        enumerable:false,//不可枚举
        writable:true,
        value:10
})
console.log(obj)//此时发现a时一个不可枚举的属性

不可枚举属性简单来说就是你无法用for in来获取遍历,他是不想暴露的属性。

var obj = {};
Object.defineProperty(obj,"a",{
        configurable:true,
        enumerable:true,
        writable:false,//不可写
        value:10
    })
obj.a=100;//修改无效,他是一个只读属性

当你啥都没写时,他们的默认值都为false

Object.defineProperty(obj,"a",{
        // 描述属性省略时默认值是false
        //意思为他无法被删除,修改同时也是不可枚举属性
        value:function(){
            console.log("aaa");
        }
    })
Object.defineProperties()

当需要追加多个属性和属性值时,可以使用这个方法

 var obj= {};
 Object.defineProperties(obj,{
        a:{
            enumerable:false,
            writable:true,
            configurable:true,
            value:10
        },
        b:{
            writable:true,
            configurable:true,
            value:function(){

            }
        },
        c:{
            configurable:true,
            value:100
        }
    })
Object.freeze()

ES6中没有常量,不过你可以使用objec.freeze()这个方法来冻结对象,他的参数为一个对象

var obj = {a:1};
Object.freeze(obj)//冻结对象,此时他无法增加追加删除
delete.obj.a//无法删除
obj.b=100;//无法增加
obj.a=100//无法修改
Object.getOwnPropertyNames()

获取对象的所有属性名,同时包括不可枚举属性,参数为需要获取的对象

Object.getOwnPropertyDescriptor()

获取对象属性的描述对象,参数为需要获取的对象和属性名称。

以为我们有时候需要遍历到对象中所有属性和属性值,使用for in时无法遍历到不可枚举对象,此时利用上述两种方法就可以完成对象的遍历。

Object.defineProperties(obj,{
            a:{
                value:1
            },
            b:{
                enumerable:true,
                value:2
            },
            c:{
                writable:true,
                value:3
            }
        });
        obj.d=10;
        obj.e=100;
 var arr=Object.getOwnPropertyNames(obj);
  for(var i=0;i<arr.length;i++){
         console.log(arr[i],obj[arr[i]]);
  var disc=Object.getOwnPropertyDescriptor(obj,arr[i]);
            console.log(disc);
        } 
Object.is()

用来判断两个参数是否相等,类似于全等(===),返回一个Boolean值

但是和全等不同的时使用object.is判断NaN时是相等的

console.log(object.is(NaN,NaN))

另外还有一些方法返回的都是Boolean值

 console.log( Object.isExtensible(obj));//判断对象是可以增加属性
 console.log(Object.isFrozen(obj))//判断对象是否冻结
obj.hasOwnProperty()

用来判断对象中是否存在这个属性,类似于in,不过和in不同的是,它所判断的是当前对象的对象属性,原型链不属于当前范围,而用in判断是否存在时,它所判断的时当前对象和对象原型链中所有属性都可以判断

   var o={a:1,b:2};
   var o1=Object.create(o);
  console.log(o1.hasOwnProperty("a"));//false,当前对象的对象属性,原型链属性不属于范围
 console.log("a" in o1);//true
isPrototypeOf()

用来判断一个类的父类是否用于这个类

 class Box{
            constructor(){

            }
            play(){

            }     
        }
  class Ball extends Box{
            constructor(){
                super();
            }
            run(){

            }
        }
console.log(Box.isPrototypeOf(Ball));//Ball的父类是否有Box类
var a=new Ball();
console.log(Box.isPrototypeOf(a.constructor));//b对象的父类中有没有Box类

propertyIsEnumerable()

用来查询属性是不是可枚举属性

var obj = {a:1,b:2}
console.log(obj.propertyIsEnumerable("b"))
instanceof

用来判断实例化对象中的原型上有没有这个类

 class Box{
            constructor(){

            }
            play(){

            }     
        }
  class Ball extends Box{
            constructor(){
                super();
            }
            run(){

            }
        }   
   var b=new Box();
   console.log(b instanceof Box);
   console.log(b instanceof Ball);

对象深复制的封装

 function cloneobj(source,target){
            if(target===undefined) target = {};
            var names = Object.getOwnPropertyNames(source);
            for(var i = 0; i < names.length;i++){
                var desc = Object.getOwnPropertyDescriptor(source,names[i]);
                if(typeof desc.value==='object' && desc.value !== null){
                    var obj;
                    switch(true){
                        case desc.value.constructor === Date:
                        obj = new Date(desc.value.toString());
                        break;
                        case desc.value.constructor === RegExp:
                        obj = new RegExp(desc.value.source,desc.value.flags);
                        break;
                        case HTMLElement.isPrototypeOf(desc.value.constructor):
                        obj = document.createElement(desc.value.nodeName);
                        break;
                        default:
                        obj = new desc.value.constructor()
                    }
                    Object.defineProperty(target,names[i],{
                        enumerable : desc.enumerable,
                        writable : desc.writable,
                        configurable : desc.configurable,
                        value : obj
                    })
                    cloneobj(desc.value,obj)
                }else{
                    Object.defineProperty(target,names[i],desc)
                }
            }
            return target
        }

使用时直接调用:

 var obj = {
            a: 1,
            b: 2,
            c: [1, 2, 3],
            z: document.createElement("div"),
            d: {
                e: new Date(),
                f: /a/g,
                g: function (s) {
                    console.log(s);
                },
                h: {

                }
            }
        }
        Object.defineProperties(obj.d.h, {
            i: {
                value: 10
            },
            j: {
                configurable: true,
                value: [1, 2, 3, 4]
            },
            k: {
                writable: true,
                value: {
                    l: {},
                    m: "abcde",
                    n: true,
                    o: [1, 2, 3]
                }
            }
        })
        Object.defineProperties(obj.d.h.k.l, {
            p: {
                value: function () {
                    console.log("p")
                }
            },
            q: {
                value: {
                    r: { a: 1 },
                    j: { b: 2 }
                }
            }
        });
      var o ={a:1};
       o = cloneobj(obj);
      console.log(o)