JS中的对象
属性的基本操作方法
对属性的访问,添加,删除
let obj = {
name: '小明',
age: 20
}
//访问
console.log(obj.name)
console.log(obj['age'])
//添加
obj.sex = '男'
obj['sex'] = '男'
console.log(obj.sex)
//删除
delete obj.sex
console.log(obj)
对象是引用类型
对象是引用类型,在进行"="赋值,或者作为参数传递操作时候不是简单的传递值,而是传递地址。
let obj = {
name: '小明',
age: 20
}
setAge(obj){
obj.age = 30
console.log('我是局部变量obj,这是我的age:',obj.age)
}
console.log("我是全局变量obj,这是我的age:",obj.age)
//按照道理说,里面的局部变量和外面的全局变量各不相干。可是打印age结果是一模一样,说明虽然他们是不同的作用域活动,但是包含的是地址,地址是指向同一片空间,说白了就是这些变量都公用一个值。
对象中的扩展运算符
我一直都是理解的是…符号会去掉{}
let obj = {
name: '小明',
age: 20
}
let otherInfo = {
sex: '男'
}
obj = {...otherInfo,...obj}
console.log('最总结果:',obj)
对象中的解构赋值
我一直都是理解的是一一对应关系
let obj = {
name: '小明',
age: 20,
sex: '男',
like: 'basketball'
}
//声明与obj中属性相同的变量名字来接受obj中属性,
//声明的变量和属性名相同
//'='的左边必须是{},
const {
//接受2个或者全部
name,
age
} = obj
const{
//接收一个
sex
} = obj
console.log('name:',name)
console.log('age:',age)
console.log('sex:',sex)
连续解构
前面的解构的对象里面的属性要么是字符串,要么是数字。如果遇到复杂的数据结构呢?
let obj = {
title:'美好的一天',
content:{
first: '今天天气不错',
second: '去野外郊游',
third: '今天真是愉快的一天'
}
}
//记住下面的解构
// 我总结一句,就是原来的obj怎么写,就怎么写,然后:后面是字符串或者数字,直接删除。
const {
title,
content:{
first,
second,
third
}
} = obj
console.log('title:',title)
console.log('first:',first)
console.log('second',second)
console.log('third',third)
解构对象中不存在的属性
你也可以认为这点知识点是在给对象默认值,因为还记得吗,解构的左边是必须{},这本身也是一个对象,不过没名字而已。
不存在肯定是undefined,那我们给他默认值吧
let obj = {
name: '小明',
age: 18
}
const {
name,
age,
sex = '男'
} = obj
consol.log(sex)
监测是否含有某个属性
let obj = {
name: '小明',
sex: '男'
}
console.log(obj.hasOwnProperty('name'))
//console.log('age' in obj),这个是监测他自身和原型是否含有,
//这里先不讲述什么是原型。
对象合并
任然是理解去掉{}
let obj1 = {
name:"小明"
}
let obj2 = {
age: 18
}
let obj = Object.assign(obj1,obj2)
console.log(obj)
object的快速遍历
//快速度获取object的所有属性,并输出成数组
let obj = {
name: '小明',
sex: '男'
}
console.log("属性",Object.keys(obj))
//快速度获取object的所有属性值,并输出成数组
console.log("属性值",Object.values(obj))
//快速度获取object的所有属性和属性值,并输出成数组
console.log("属性and属性值",Object.entries(obj))
对象的深浅拷贝
浅拷贝系列
//1
let obj1 = {
name: '小明',
sex: '男'
}
let obj2 = obj1
//2
let obj1 = {
name: '小明',
sex: '男'
}
let obj2 = Object.assign({},obj1)
//3
let obj1 = {
name: '小明',
sex: '男'
}
let obj2 = {...obj1}
//4
let obj1 = {
name: '小明',
sex: '男'
}
let obj2 = {
name: obj1.name,
sex: obj1.sex
}
深拷贝系列
//深拷贝1
function copy(obj){
let res = obj instanceof Array ? [] : {};
for(const [k,v] of Object.entries(obj)){
//递归监测
res[k] = typeof v == 'object' ? copy(v) : v;
}
return res;
}
//深拷贝2
const obj1 = {
age: 20,
name: 'xxx',
address: {
city: 'beijing'
},
arr: ['a', 'b', 'c']
}
function deepClone(obj = {}) {
if (typeof obj !== 'object' || obj == null) {
// obj 是 null ,或者不是对象和数组,直接返回
return obj
}
// 初始化返回结果
let result
if (obj instanceof Array) {
result = []
} else {
result = {}
}
for (let key in obj) {
// 保证 key 不是原型的属性
if (obj.hasOwnProperty(key)) {
// 递归调用!!!
result[key] = deepClone(obj[key])
}
}
// 返回结果
return result
}
属性描述符
//打印出来就知道了
let obj = {
name: '小明',
sex: '男'
}
console.log(Object.getOwnPropertyDescriptor(obj,'name'))
//{value: "小明", writable: true, enumerable: true, configurable: true}
//值,是否可写,是否可遍历,是否重新配置
//查看所有的属性,注意这里末尾是有一个s,console.log(Object.getOwnPropertyDescriptors(obj))
修改属性描述符
//打印出来就知道了
let obj = {
name: '小明',
sex: '男'
}
console.log(Object.getOwnPropertyDescriptor(obj,'name'))
//{value: "小明", writable: true, enumerable: true, configurable: true}
Object.defineProperty(obj,'name',{
value: "小刚",
writable: true,
enumerable: false,
configurable: true
})
console.log(Object.getOwnPropertyDescriptor(obj,'name'))
//{value: "小刚", writable: true, enumerable: false, configurable: true}
给属性描述符设置规定
let obj = {
name: '小明',
sex: '男'
}
//这个只会禁止添加
Object.preventExtensions(obj)
//判断
Object.isExtensible(obj)
//这个是禁止添加,删除,修改
Object.freeze(obj)
Object.isFrozen(obj)
//还有一个很相似,不过这个是禁止添加,删除 => configurable=false
Object.seal(obj)
Object.isSead(obj)
对象的getter与setter
理解为保护对象,而提供get与set的api进行访问
//隐藏真正的属性_age,只能访问age这个接口,每次修改必须经过set
_age = 18 //保护起来的属性值
let obj = {
name:'小明',
age: _age,
sex:'男',
set age(val){
if(val < 25 && val>0){
_age = val
}
},
get age(){
return _age
}
}
console.log(obj)
console.log(obj.age)
obj.age = 99
console.log(obj.age)
obj.age = 15
console.log(obj.age)
proxy代理
好比一个中间人,不让直接接触数据。
因为代理的存在,我们可以对操作进行拦截
然后看到这里我也还没搞懂前面属性的setter、getter与这里的代理有啥区别,待补充
//基本语法
new Proxy(被代理的对象,{
get(被代理的对象,键){
},
set(被代理的对象,键,值){
}
})
let obj = {
name:'小明',
age: 18,
sex:'男'
}
let objProxy = new Proxy(obj,{
get(target,key){
return target[key]
},
set(target,key,value){
if(key === 'age'){
if(value < 25 && value>0){
target[key] = value
}else{
console.log("err")
}
}
}
})
console.log(objProxy)
objProxy.age = 15
console.log(objProxy)
objProxy.age = 28
console.log(obj)
JSON的形式
本质就是和对象一样的键值对,但是注意不是对象
json就是一种通用的数据交互格式,可以理解为中国话里面的普通话。无论是到哪个省份,你说普通话都行。
//语法格式
{
"key1":"value1",
"key2":"value2",
"key3":"value3",
"key4":"value4",
}
//在js中把对象数据结构转化为json,js不仅仅对象可以和json互相转,其他数据结构也是可以的
let obj = {
name:'小明',
age: 18,
sex:'男'
}
let json = JSON.stringify(obj)
console.log(json)
//把json转化成对象
let obj1 = JSON.parse(json)
console.log(obj1)
JSON.stringify进阶
JSON.stringify(待转换的对象,保留的属性,缩进)
let obj = {
name:'小明',
age: 18,
sex:'男'
}
let json = JSON.stringify(obj,['name','age'],2)
console.log(json)
JSON.parse进阶
let obj = {
name:'小明',
age: 18,
sex:'男'
}
let json = JSON.stringify(obj)//获取json形式
let obj1 = JSON.parse(json,(key,value)=>{
console.log(`${key}---${value}`)
})//把json转化成对象
console.log(obj1)