JavaScript之Object类


Object类

概述

  • JavaScript的内置的类,任何自定义函数的默认原型就是Object类的一个对象。所以自己创建的对象能够直接通过原型链使用Object定义的api

Object API

Object.create()

  • 创建一个对象。特点是可以手动指定新对象的原型,可以为null
let o = Object.create(null);//该新对象没有原型,
//第一个参数设置对象的__proto__ 属性,第二个参数设置自身属性
let obj=Object.creat({a:1},{
    //自身的属性,必须是对象
    b:{
        //descriptor
        value:属性值,
        configurable:是否可配置,默认为false,
        writable: 是否可更改,默认为false
        enumerable: 是否可枚举 默认值为false
    }
})
  • 如果传递的参数为null,那么该新对象没有任何原型。哪怕Object提供的api也不能使用

Object.assign()

  • 完成多个对象的合并,源对象有可枚举的特性

            //目标对象     源对象
    Object.assign(target,...source)
    //原理是返回的一个target对象,枚举源对象的属性,(只会分配键值对)分配给target目标对象然后返回
    //属性的设置添加 getter 和 setter  存取运算符
    
  • 不会将原型中的属性进行分配

  • 面试题

    const v1=123;
    const v2='123';
    const v3=true;
    const v4=function test(){ };
    const v5=Object.assign({},v1,v2,v3,v4);
    console.log(v5)
    /*0  1
       1  2
       2  3  */
    

Object.defineProperty

  • 给某个对象添加或修改某个属性的值(详细)

    //三个参数;
    /*
    第一个参数:目标对象
    第二个参数:需要添加的属性
    第三个参数:属性描述器
    */
    const target =Object.defineProperty({ },"a",{
        value:'属性值',
        writtable:是否可以被更改,默认为false,
        enumrable:是否可枚举,默认为false,
        configurable: 是否可配置(是否可以被删除),默认为false//在读取该对象的a属性时,get函数(getter)就会被调用,且返回值就是属性a的值  
       get:function(){
        return 'helo' },
      //在修改该对象的a属性时,set函数(setter)就会被调用,且会收到修改的具体值 
        set(value){
            
        }
    });
    

hasOwnProperty

  • 判断某个属性是否是自己的属性,不考虑继承过来的属性。

    function Sun(){
        this.age = 12;
    }
    Sun.prototype.name = '张三';
    let s = new Sun();
    console.log(s.name);
    console.log(s.hasOwnProperty('name'));//false
    

其他Api

  • Object.freeze():冻结一个对象。冻结即该对象不可修改
  • Object.isFrozen():判断一个对象是否冻结,返回布尔型
  • propertyIsEnumable():判断一个对象的某个属性是否可枚举。
  • Object.is()-ES6:判断两个数据是否一致,类似于===,只是判断NaN是否等于NaN时为true
  • Object.assign()-ES6:将多个对象进行合并,一般用于对象复制
  • toString():对象的字符串输出.
  • Object.keys(对象参数)将传入对象的所有属性名提取出来,返回一个数组

枚举

  • 概念:枚举是指对象中的 某个属性是否可以被遍历出来。
  • 特点:用户定义的属性默认都是可以枚举的
  • 改变枚举:Object.defineProperty()
let o = {
    name:'张三',
    age:12
};
//设置age属性为不可枚举(不可被遍历)
Object.defineProperty(o,'age',{
    value:12,
    //不可枚举
    enumerable:false
});

浅克隆和深克隆(针对引用类型数据)

无论是浅拷贝或深拷贝,都是在做同一件事情:拷贝对象

浅克隆

  • 遍历
  • 扩展运算符
let o1 = {
    name:'张三',
    age:12,
    sex:'男'
}
//扩展
//let o2 = {...o1};
//遍历
let o2 = {};
for (const key in o1){
    //将o1的属性赋给o2
    o2[key] = o1[key];
}
console.log(o2,o1);

浅克隆问题:当对象中的某个属性的值也是一个对象时,拷贝该属性时只是把对象的地址给拷贝过去了,所以拷贝的该属性无论是新对象还是旧对象,针对该属性,都是指的同一个属性值(对象)

深克隆

  • 原理:对属性值是对象的属性也进行一次浅克隆(即使用递归)

方式:

  1. 递归方式返回一个新对象(更灵活)
  2. JSON转换为字符串,有缺陷,若属性值为’null’ ,转换之后与之前对象不匹配
  3. Object.assign() 对象的合并
  4. 扩展运算符{…Object};
ES5深克隆
function deepClone(origin,target){
    //创建一个空对象
    var tar= target || {}var toStr=Object.prototype.toString;
    var arrType="[object Array]"//遍历对象
    for(var k in origin){
        //自身的属性进行克隆
        if(origin.hasOwnProperty(k)){
            //判断属性是否是对象并且不为null   null的类型也为object
            if(typeof  origin[k]==='object' && origin[k]!==null){
                //判断是否为数组
                tar[k]=toStr.call(origin[k])===arrType? []:{};
                //递归调用,将属性值为对象的属性值再次克隆
                deepClone(origin[k],tar[k]);
            }else {
                //非对象直接将属性值添加到目标对象中
                tar[k]=origin[k];
            }
        }
    }    
}

ES6

function deepClone(origin){
    //undefined 和 null == 结果为true
    if(origin== undefined || typeof origin !=='object'){
        return origin;
    }
    //对于特殊的对象返回
    if(origin instanceof Date){
        return new Date(origin);
    }
    //调用源对象的构造函数,创建一个新的对象
    const target = new origin.constructor();
    for(let k in origin){
        if(origin.hasOwnProperty(k)){
            target[k]=deepClone(origin[k]);
        }
    }
    return target;
}

文章作者: 时光路人
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 时光路人 !
评论
  目录