目录
getOwnPropertyDescriptor(获取对象属性的配置)
getOwnPropertyDescriptors(查看对象所有属性配置)
getOwnPropertySymbols(属性名为Symbol类型的集合)
isPrototypeOf(判断一个对象的原型链上是否存在另一个对象)
propertyIsEnumerable(判断属性是否可枚举)
因为你不论在业务开发中还是看一些源代码的时候,都会有用到对象的方法,常用的和冷门多少都会用到。
最经典的莫过于,Object.defineProperty,这个方法想必很多人都知道。
在业务开发中,基本不会用到这个方法,但是vue2中的响应式这个方法是关键点之一,所以这个方法也是很重要的。如果你想去看vue2的源码,但是你却不懂defineProperty的作用,那你就得回头再看,耽误事
console.log(Object.prototype,'对象方法')
所以,对象的方法你还是需要会的,就算你不能一次性都记住这些属性的全部使用方法,但是你也得都过一遍,至少知道每一个方法大致都是干啥的。
参数1:目标对象
参数2:新对象
将两个合并,如果目标对象和新对象的属性重合,新对象的属性会覆盖目标对象的值
修改后的目标对象
//assign
let obj1 = {name:'wjt'}
let obj2 = {age:29}
let newObj1 = Object.assign(obj1,obj2)
console.log(newObj1,'合并后的对象')
console.log(obj1,'修改后的')
console.log(newObj1 === obj1,'是否相等')
let obj3 = {name:'wjt',age:28}
let obj4 = {love:'javascript',age:29}
Object.assign(obj3,obj4)
console.log(obj3,'属性覆盖')
let obj5 = {}
let obj6 = {name:'wjt',age:28,wife:{name:'xiaoma',age:28}}
Object.assign(obj5,obj6)
obj6.age = 29
console.log(obj5,'修改第一层的属性')
obj6.wife.age = 29
console.log(obj6,'修改第二层的属性')
1.参数1和参数2都是对象类型,该方法可以将参数2对象合并到参数1身上
2.属性重合,参数2的值会覆盖参数1的值
3.返回值等于参数1,也就是说会改变参数1对象
4.可以实现一层的对象数据深拷贝,但是如果如果层级超过1级,就是浅拷贝了
原型对象
以一个现有对象作为原型对象,创建一个新对象。
新对象
let personObj = {work:'coder',sex:'man'}
let yyx = Object.create(personObj)
yyx.name = '尤雨溪'
let wjt = Object.create(personObj)
wjt.name = '王惊涛'
console.log(yyx,yyx.work,'前端大佬-尤大大')
console.log(wjt,'前端菜狗-王惊涛')
?
将一个源对象作为原型对象,创建新的对象,每一个创建的新对象上可以访问源对象上的属性
参数1:操作对象
后续参数:属性名:{value:属性值,writable:是否可修改}
对一个对象的属性进行新增,并且可以配置该属性是否可以修改
操作完的对象
//defineProperties
let wjt = {}
Object.defineProperties(wjt,{
name:{
value:'wjt',
writable:false //不可修改
},
age:{
value:28,
writable:true //可修改
}
})
console.log(wjt,'wjt对象')
wjt.name = 'wangjingtao'
wjt.age = 29
console.log(wjt,'修改后的wjt对象')
可以对一个对象的属性进行定义,并且可以设置writable值来决定是否可以被修改
参数1:要操作的对象
参数2:属性名
参数3:配置
会直接在一个对象上定义一个新属性,或修改其现有属性,并返回此对象。
传入函数的对象,其指定的属性已被添加或修改。
let wjt = {}
Object.defineProperty(wjt,'name',{
value:'wjt',
writable:false, //是否可以修改
enumerable:true, //是否可以枚举
configurable:false //不可以删除,默认是false
})
Object.defineProperty(wjt,'age',{
value:29,
writable:true,
enumerable:true
})
Object.defineProperty(wjt,'privacy',{
value:()=>{console.log('个人的隐私信息,不想让别人知道')},
writable:true,
enumerable:false, //不可被枚举
configurable:true //可以删除
})
console.log(wjt,'对象信息')
for(let value in wjt){
console.log(value,wjt[value],'迭代对象')
}
//数据代理
let wjt = {name:'wjt',age:29,work:'coder'} //字面量定义的对象数据
let _wjt = {} //代理对象
console.log(wjt,'初始化的源对象')
console.log(_wjt,'初始化的代理对象')
Object.defineProperty(_wjt,'name',{
get(){
console.log('访问_wjt的name属性,我给他返回wjt的name属性')
return wjt.name
},
set(value){
console.log('修改了_wjt.name的属性,但其实这里我会把wjt.name也给改了')
wjt.name = value
}
})
console.log(_wjt.name,'查看_wjt的name属性')
_wjt.name = 'wangjingtao'
console.log(wjt,'源对象')
console.log(_wjt,'代理对象')
这里我们点开最后的一行输出,看看发生了什么
点开name属性
其实这里我们实现了几点功能:
1.定义新属性,并可以决定他是否可以被修改,删除,被迭代捕捉到
2.可以对对象中具体属性的get和set进行重写
3.可以通过代理,监听到对象的查询和修改
可以是对象,或者类数组
返回一个数组,包含给定对象自有的可枚举字符串键属性的键值对
返回的是键值匹配的数组
//对象
let wjt = {name:'wjt',age:28,work:'coder'}
console.log(Object.entries(wjt),'遍历了对象')
//类数组
let classArr = {0:'wjt',1:28,3:'coder'}
console.log(Object.entries(classArr),'遍历类数组')
//和Map配合使用
let newMap = new Map(Object.entries(wjt))
console.log(newMap,'正好我Map要的就是这种数据类型')
console.log(newMap.get('name'),'访问Map中的name属性')
1.可以对对象和类数组进行迭代,生成数组
2.可以和map配合使用,效果较好
要冻结的对象
冻结对象可以防止扩展,并使现有的属性不可写入和不可配置。被冻结的对象不能再被更改:不能添加新的属性,不能移除现有的属性,不能更改它们的可枚举性、可配置性、可写性或值,对象的原型也不能被重新指定。
冻结一个对象是 JavaScript 提供的最高完整性级别保护措施。
被冻结的对象
//对象
let wjt = {name:'wjt',age:28}
Object.freeze(wjt)
wjt.age = 29
console.log(wjt,'修改无效,age没变化')
wjt.love = 'LoL'
console.log(wjt,'不能添加,添加无效')
//数组
let arr = [1,2,3,4,5]
Object.freeze(arr)
arr[0] = '新的'
console.log(arr,'修改数组无效')
arr.push(6) //报错
console.log(arr,'无法新增')
let wjt = {name:'wjt',age:28,love:{name:'LOL',hero:'虚空掠夺者'}}
Object.freeze(wjt)
wjt.age = 29
wjt.love.hero = '嘉文四世'
console.log(wjt,'第一层的不能改,但是内部属性如果是对象,是可以修改对象内的变量值的')
1.可以冻结数组和对象,修改,删除,新增属性都不可以
2.冻结只能冻结对象内值类型的值,如果是引用类型,是可以修改对象内的属性值的,相当于是浅冻结
迭代对象,数组或者Map
将键值对列表转换为一个对象。
一个对象
let arr = [["name","wjt"],["age",28]]
let wjt1 = Object.fromEntries(arr)
console.log(wjt1,'数组转对象')
let map = new Map([["name","wjt"],["age",28]])
let wjt2 = Object.fromEntries(map)
console.log(wjt2,'map转对象')
可迭代的类型:数组和map都可以使用这个方法转化为对象
参数1:对象
参数2:属性值
返回一个对象,该对象描述给定对象上特定属性(即直接存在于对象上而不在对象的原型链中的属性)的配置
属性值的配置:对象类型,如果不存在,返回undefined
//getOwnPropertyDescriptor
class Coder{
done = ()=>{console.log('正常生理活动')}
constructor(name,age){
this.name = name
this.age = age
this.type = 'person'
}
}
let wjt = new Coder('wjt',28)
console.log(wjt,'创建的对象')
let prop1 = Object.getOwnPropertyDescriptor(wjt,'name')
let prop2 = Object.getOwnPropertyDescriptor(wjt,'type')
let prop3 = Object.getOwnPropertyDescriptor(wjt,'done')
let prop4 = Object.getOwnPropertyDescriptor(wjt,'not')
console.log(prop1,'自定义的属性')
console.log(prop2,'原型上的属性1')
console.log(prop3,'原型上的属性2')
console.log(prop4,'不存在的属性')
可以对对象上的属性配置状态进行查询,看是否可以修改,删除,枚举等
对象
查看对象上所有属性的配置
配置信息组成的对象
let wjt = {name:'wjt',age:29}
console.log(Object.getOwnPropertyDescriptors(wjt),'全属性配置')
可以查看对象内所有属性(自己定义的)的配置
对象
返回一个数组,其包含给定对象中所有自有属性(包括不可枚举属性,但不包括使用 symbol 值作为名称的属性)
属性名组成的数组
let wjt = {name:'wjt',age:28,work:'coder'}
console.log(Object.getOwnPropertyNames(wjt),'属性名集合')
将对象内的自有属性名称组成一个数组
对象
返回一个包含给定对象所有自有 Symbol 属性的数组。
对象所有自有 Symbol 属性的数组
let wjt = {}
let name = Symbol('name')
let age = Symbol('age')
wjt[name] = 'wjt'
wjt[age] = 28
wjt.work = 'coder'
console.log(wjt,'对象')
console.log(Object.getOwnPropertySymbols(wjt),'symbol信息的属性')
属性名只有是Symbol类型,才能被获取到加入数组,该方法用来判定对象内的Symbol属性名
有原型对象的数据,(null和undefined不可以)
返回指定对象的原型(即内部?[[Prototype]]
?属性的值)
返回指定对象的原型(即内部?[[Prototype]]
?属性的值)
let obj = {name:'wjt',age:29}
console.log(Object.getPrototypeOf(obj),'对象类型')
let arr = [1,2,3,5,6]
console.log(Object.getPrototypeOf(arr),'数组类型')
console.log(Object.getPrototypeOf(()=>{}),'函数类型')
console.log(Object.getPrototypeOf('字符串'),'字符串类型')
console.log(Object.getPrototypeOf(0),'数字类型')
console.log(Object.getPrototypeOf(true),'布尔类型')
// console.log(Object.getPrototypeOf(null),'null类型') //报错
// console.log(Object.getPrototypeOf(undefined),'undefined类型') //报错
let person = {type:'人类',done:'正常人类活动'}
let wjt = Object.create(person)
console.log(wjt,'wjt对象')
console.log(Object.getPrototypeOf(wjt),'wjt对象的原型')
console.log(Object.getPrototypeOf(wjt).__proto__ === Object.getPrototypeOf(obj),'是否相等')
返回的就是当前对象的原型对象,也就是你的__proto__
参数1:对象
参数2:属性名
如果指定的对象自身有指定的属性,返回?true
。如果属性是继承的或者不存在,该方法返回 false
true或者false
let wjt = {name:'wjt',age:28}
console.log(Object.hasOwn(wjt,'name'),'查看name属性')
console.log(Object.hasOwn(wjt,'not'),'查看不存在的属性')
console.log(Object.hasOwn(wjt,'toString'),'查看原型对象的toString属性')
可以查看对象中的某个属性是否是我们自有的,非继承的
这个方法被上面的那个方法取代了,官方推荐用上面的那个,两个方法的功能是一样的,只是写法不一样而已
//hasOwnProperty
let wjt = {name:'wjt',age:28}
console.log(wjt.hasOwnProperty('name'),'name属性')
console.log(wjt.hasOwnProperty('not'),'不存在的属性')
console.log(wjt.hasOwnProperty('toString'),'原型上的属性')
参数1:比较的值1
参数2:比较的值2
确定两个值是否为相同值
true或者false
console.log(Object.is(28,28),'相同数字')
console.log(Object.is('wjt','wjt'),'相同字符串')
console.log(Object.is(null,null),'两个null')
console.log(Object.is(undefined,undefined),'两个undefined')
console.log(Object.is(NaN,NaN),'两个NaN')
console.log(Object.is(window,window),'两个window')
let obj1 = obj2 = {name:'wjt'}
console.log(Object.is(obj1,obj2),'同一个地址的对象')
console.log('------------------------------------')
console.log(Object.is([1,2,3],[1,2,3]),'元素相同的数组')
console.log(Object.is({name:'wjt'},{name:'wjt'}),'元素相同的对象')
console.log(Object.is(()=>{},()=>{}),'两个空函数')
console.log('------------------------------------')
console.log(NaN === NaN,'NaN === NaN')
console.log(undefined === undefined,'undefined === undefined')
console.log(null === null,'null === null')
is其实主要也是对比两个数据的值是否相同,引用类型对比的是内存地址值
is和===还是有区别的,例如NaN
对象
可以防止新属性被添加到对象中(即防止该对象被扩展)。它还可以防止对象的原型被重新指定。
不可扩展的对象
let wjt = {name:'wjt',age:28}
Object.preventExtensions(wjt)
wjt.work = 'coder'
console.log(wjt,'wjt对象新增work属性失败')
让对象不可以扩展,不能新增和删除现有属性,不过你可以修改值,而且也防止对象原型被重新定义
对象
判断对象是否为可扩展的
true或者false
let wjt = {name:'wjt',age:28}
console.log(Object.isExtensible(wjt),'未防止扩展前')
Object.preventExtensions(wjt)
console.log(Object.isExtensible(wjt),'禁止扩展后')
let obj = Object.freeze({name:'wangjingtao'})
console.log(Object.isExtensible(obj),'一个被冻结的对象')
被preventExtensions和freeze这两个方法禁锢的对象,是无法进行扩展的,isExtensible用来判断是否可以对对象进行扩展操作
对象
查看对象是否被冻结
true或者false
//isFrozen
let wjt = {name:'wjt',age:28}
console.log(Object.isFrozen(wjt),'冻结前')
Object.freeze(wjt)
console.log(Object.isFrozen(wjt),'冻结后')
判断一个对象是否被冻结
对象1 isProtoytypeOf(对象2)
判断对象2的原型链上是否存在对象1
true或者false
class C1{
constructor(name,age){
this.name = name
this.age = age
this.work = 'coder'
}
}
let wjt1 = new C1('wjt',28)
function F1(name,age){
this.name = name
this.age = age
this.work = 'coder'
}
let wjt2 = new F1('wjt',28)
console.log(C1.isPrototypeOf(wjt1),'wjt1对象的原型链上有C1吗')
console.log(F1.isPrototypeOf(wjt2),'wjt2对象的原型链上有F1吗')
wjt1.__proto__ = C1
wjt2.__proto__ = F1
console.log(C1.isPrototypeOf(wjt1),'再来一次,wjt1对象的原型链上有C1吗')
console.log(F1.isPrototypeOf(wjt2),'再来一次,wjt2对象的原型链上有F1吗')
console.log('-------------------------------------')
let obj = {work:'coder'}
let wjt3 = Object.create(obj)
wjt3.name = 'wangjingtao'
wjt3.age = 28
console.log(wjt3,'wjt3对象')
console.log(obj.isPrototypeOf(wjt3),'wjt3的原型链上有obj吗')
可以判断原型链上是否存在某个对象
对象
封一个对象,会阻止其扩展并且使得现有属性不可配置。密封对象有一组固定的属性:不能添加新属性、不能删除现有属性或更改其可枚举性和可配置性、不能重新分配其原型。只要现有属性的值是可写的,它们仍然可以更改。
密封后的对象
let wjt = {name:'wjt',age:28}
Object.seal(wjt)
wjt.name = 'wangjingtao'
wjt.work = '工作'
delete wjt.age
console.log(wjt,'wjt对象')
密封的对象不能进行添加,删除等扩展操作,但是可以修改原有属性
isSealed
(判断一个对象是否被密封)对象
判断对象是否被密封
true或者false
//isSealed
let wjt = {name:'wjt',age:28}
console.log(Object.isSealed(wjt),'封禁前')
Object.seal(wjt)
console.log(Object.isSealed(wjt),'封禁后')
判断一个对象是否被封禁
对象
返回对象的可枚举属性的集合,但不包括Symbol
一个数组
let wjt = {name:'wjt',age:28}
let work = Symbol('work')
wjt[work] = 'coder'
console.log(wjt,'wjt对象')
console.log(Object.keys(wjt),'key的集合')
getOwnPropertyNames方法可以返回不可枚举的属性,keys只能返回可枚举的属性
属性名
判断属性是否是对象的可枚举自有属性
true或者false
let wjt = {name:'wjt',age:28}
let arr = [1,2,3]
console.log(wjt.propertyIsEnumerable('name'),'对象自定义的可枚举属性name')
console.log(wjt.propertyIsEnumerable('toString'),'原型上的不可枚举toString')
console.log(arr.propertyIsEnumerable(1),'自定义的可枚举索引1')
console.log(arr.propertyIsEnumerable('length'),'原型上的不可枚举的length')
可以判断属性是否是可以枚举的
参数1:指定的对象
参数2:新的原型对象
可以将一个指定对象的原型(即内部的?[[Prototype]]
?属性)设置为另一个对象或者?null。
指定的对象
let wjt = {name:'wjt',age:28}
let coder = {work:'coder'}
Object.setPrototypeOf(wjt,coder)
console.log(wjt,'更换原型为coder后的wjt对象')
?
Object.setPrototypeOf(wjt,null)
console.log(wjt,'更换原型为null后的wjt对象')
?
可以替换一个对象的原型对象
没有参数。但是,重写此方法的所有对象最多只能接受两个参数,分别对应于?locales
?和?options
,例如?Date.prototype.toLocaleString。这些参数位置不应该用于任何其他目的。
返回一个表示对象的字符串。该方法旨在由派生对象重写,以达到其特定于语言环境的目的。
特定字符串
let date = new Date(Date.UTC(2023, 12, 29, 16, 40, 10))
console.log(date.toLocaleString('ar-EG'))
console.log(date.toLocaleString('en-EN'))
console.log(date.toLocaleString('zh-ZH'))
这个方法对我来说实属冷门了,恕我着实没有用到过,也不知道场景....不过我知道参数可以传递语言类型
默认情况下,toString()
?不接受任何参数。然而,继承自?Object
?的对象可能用它们自己的实现重写它,这些实现可以接受参数。例如,Number.prototype.toString()?和?BigInt.prototype.toString()?方法接受一个可选的?radix
?参数。
返回一个表示该对象的字符串。该方法旨在重写(自定义)派生类对象的类型转换的逻辑。
字符串
console.log({name:'wjt',age:28}.toString(),'对象')
console.log([1,2,3,4].toString(),'数组')
console.log(new String('常规字符串').toString(),'字符串')
console.log(new Number(123).toString(),'普通数字')
console.log(new Number(NaN).toString(),'NaN')
console.log(new Function(()=>{}).toString(),'函数')
console.log(new Boolean(false).toString(),'布尔值')
console.log(Symbol('id').toString(),'symbol类型')
console.log(BigInt(111111111111111).toString(),'BigInt类型')
?
可以将对象类型或者包装值转化为字符串
想通过toString进行数据类型判断可以查看这篇文档
https://wangjingtao.blog.csdn.net/article/details/132453652
this
?值转化为对象)对象
将?this
?值转换成对象。该方法旨在被派生对象重写,以实现自定义类型转换逻辑。
转换成对象的?this
?值
function Fn(name,age){
this.name = name
this.age = age
}
Fn.prototype.valueOf = function(){
return this.age
}
let wjt = new Fn('wjt',28)
console.log(wjt,'wjt对象')
console.log(wjt+1,'wjt这个时候调用就是this.age,也就是28')
强制扭转this的指向,牛逼
对象
返回一个给定对象的自有可枚举字符串键属性值组成的数组
返回一个给定对象的自有可枚举字符串键属性值组成的数组
let wjt = {name:'wjt',age:28,work:'coder'}
console.log(Object.values(wjt),'对象值集合')
let arr = [1,2,3,4]
console.log(Object.values(arr),'数组值集合')
?
可以获取对象可枚举属性的值
object方法其实很多我们在开发业务中用的还真不多,但是在框架中应用的很多
还是那句话,你就算记不住所有方法,你至少看一遍,知道Object都可以实现什么功能,看框架和源码之前可以来全量的看一下
总结起来还是很耗时间的,万字长文不容易,让我去你们的收藏夹吃灰去吧!!!