JS-面向对象编程(属性描述对象)

287 阅读3分钟

Object.prototype.propertyIsEnumerable()

//判断某个属性是否可以遍历,只能判断实例对象本身属性,不可枚举属性以及继承而来的属性一律为false
//可枚举:可以遍历的属性
var obj = {};
obj.a =123;
console.log(obj.propertyIsEnumerable('a'));//true
console.log(obj.propertyIsEnumerable('toString'));//false
for(var key in obj){
    console.log(key);//a
    console.log(obj[key]);//123
}
var arr = [1, 2, 3];
console.log(arr.propertyIsEnumerable('length'));//false

getOwnPropertyDescription()

//可以获取属性描述对象,它的第一个参数是目标对象,第二个参数是一个字符串(目标对象的属性名)
var arr = [1,23,4];
console.log(arr['length']);
console.log(Object.getOwnPropertyDescriptor(arr,'0'));
/*{value: 1, writable: true, enumerable: true, configurable: true}
    configurable: true
    enumerable: true
    value: 1
    writable: true
    __proto__: Object */
console.log(Object.getOwnPropertyDescriptor(arr,'length'));
/*{value: 3, writable: true, enumerable: false, configurable: false}
    configurable: false  可配置型 false为不可被删除
    enumerable: false 不能被遍历出来
    value: 3
    writable: true  可以被读写
    __proto__: Object */
console.log(Object.getOwnPropertyDescriptor(arr,'toString'));//undefined
//不能用于继承的属性 只能用于对象自身的属

/Objcet.defineProperty()

//Objcet.defineProperty(属性所在的对象,属性名,属性描述对象)
var obj = Object.defineProperty({},'name',{
    value:'qaq',
    writable:false, //可写性
    enumrable:true, //可遍历
    configurable:false, //是否能被删除
})
console.log(obj);
obj.name = 'aaa';
console.log(obj.name);//qaq
delete obj.name;
console.log(obj.name);//qaq

Object.defineProperties()

var obj = Object.defineProperties({},{
    p1:{
    value:1,
    enumerable:true
    },
    p2:{
    value:'qaq',
    enumerable:false
    },
    p3:{
    get:function(){
        return this.p1 + this.p2
    },//value与get不能同时存在
    enumerable:true,
    configurable:true
    }
})
console.log(obj);
/*{p1: 1, p2: 2}
    p1: 1
    p3: "1qaq"
    p2: "qaq"
    get p3: ƒ () */
			
//一旦定义了取值函数get,就不能同时定义writable以及value
var obj2 = Object.defineProperty({},'a',{
    writable:true,
    get : function(){
        return 111;
    }
})
console.log(obj2.a);//报错

value、writable

//value
var obj = {};
obj.p = 123;
console.log(Object.getOwnPropertyDescriptor(obj,'p').value);//123
Object.defineProperty(obj,'p',{value : 456});
console.log(obj.p);//456

//writable 是否可以改变
var obj = {};
obj.p = 123;
Object.defineProperty(obj,'p',{
    value:890,
    writable:false
});
console.log(obj.p);//890
obj.p = 100;
console.log(obj.p);//89

enumrable、defineProperties

enumrable可遍历性,一旦enumrable设置为false,通常以下三个操作不会取到该属性。for...in、Object.keys()、JSON.stringify()。
ps:继承来的属性是可以被这三个操作取到的

configurable 可配置性,决定是否可以修改属性描述对象。 一旦设置configurable为false,属性描述对象 value、writable、enumable、configurable都不能被修改
特殊情况

  1. 在configurable为false情况下,writable从true改成false是可行的
  2. 只要writable和configurable有一个为true,value就允许被修改
  3. configurable一旦设置了true 属性可被删除,false不可被删除

深拷贝,浅拷贝

  1. 浅拷贝:与深拷贝相反,有影响的为浅拷贝
    本质上不是直接赋值,浅拷贝新建了一个对象,将原来对象的属性都一一的复制过来,复制的是指,不是引用。浅拷贝的复制只复制了第一层的属性,并没有递归所有的值复制归来。例如一个对象中的数组(对象),只复制了数组(对象) 没有吧数组(对象)里的值复制过来
  2. 深拷贝:操作拷贝之后的对象的某个属性不会影响原始对象的属性,这种拷贝是深拷贝。
    本质上深拷贝对目标对象完全拷贝,不像浅拷贝那样只是复制了一层引用,就连值也复制过来。只要进行了深拷贝,两者便老死不相往来,谁也不影响谁。