带你认识不一样的对象,Object中追加属性以及assign、isPrototypeOf等大多对象方法以及深复制的使用
对象
原型链 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:false, value: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);//trueisPrototypeOf()
用来判断一个类的父类是否用于这个类
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)
- JS中isPrototypeOf 和hasOwnProperty 的区别 ------- js使用in和hasOwnProperty获取对象属性的区别
- Object 对象方法学习之(1)—— 使用 Object.assign 复制对象、合并对象
- Object 对象方法学习之(1)—— 使用 Object.assign 复制对象、合并对象
- Object.assign() 方法用于将所有可枚举的属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
- Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
- BeanUtils.copyProperties方法的缺点以及如何使用反射完成两个对象属性的自动复制封装
- js中的hasOwnProperty和isPrototypeOf方法使用实例
- java.io 流的几个对象以及方法属性的使用
- Ruby之旅(二) Ruby的基本语法以及对象的使用,方法的定义及调用,属性的定义及使用
- ajax利用html5新特性带进度条上传文件 html5的FormData对象和input的file属性以及window.URL.createObjectURL( ) 方法
- js中的hasOwnProperty和isPrototypeOf方法使用实例
- JavaScript 复制对象【Object.assign方法无法实现深复制】
- java中equals和==之间的区别?clone方法的作用,及其为什么要使用clone方法?如何使用clone复制对象?以及深克隆浅克隆
- ES6新特性---对象扩展方法Object.assign、Object.is、Proxy与Object.defineProperty
- javascript 对象及原型继承有关的属性:constructor、prototype、isPrototypeOf、instanceof、in 、hasOwnProperty 等等
- js object 对象 属性和方法的使用
- Ruby之旅(二) Ruby的基本语法以及对象的使用,方法的定义及调用,属性的定义及使用
- Object.setPrototypeOf 方法的使用
- es6 javascript对象方法Object.assign() 对象的合并复制等
- javascript 对象及原型继承有关的属性:constructor、prototype、isPrototypeOf、instanceof、in 、hasOwnProperty 等等...