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时为trueObject.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);
浅克隆问题:当对象中的某个属性的值也是一个对象时,拷贝该属性时只是把对象的地址给拷贝过去了,所以拷贝的该属性无论是新对象还是旧对象,针对该属性,都是指的同一个属性值(对象)
深克隆
- 原理:对属性值是对象的属性也进行一次浅克隆(即使用递归)
方式:
- 递归方式返回一个新对象(更灵活)
- JSON转换为字符串,有缺陷,若属性值为’null’ ,转换之后与之前对象不匹配
- Object.assign() 对象的合并
- 扩展运算符{…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;
}