属性的添加
1.直接使用点语法添加
let obj={}
obj.name='xiaocao';
console.log(obj)//{name:'xiaocao'}
2.方括号添加
let obj={}
obj['name']='xiaocao';
//注意:不能直接obj[name]来添加属性,这种办法会从obj中寻找name变量,找不到就会报错
console.log(obj)//{name:'xiaocao'}
对象与原型链属性检测
1.检测自身属性
obj.hasOwnProperty(属性名)
2.检测包括父级作用域的属性
console.log("concat" in arr)
//"检测的属性" in 检测的对象
计算属性与assign的使用
1.Object.assign()
2.Object.keys()可以获取所有属性的名字
3.object.values()可以获取所有属性的值
//分开获取一个对象的值和名
//使用for in方法
for (const key in obj){
console.log(obj[key])//获取值
console.log(key)//获取名
}
//通过解构的办法获取
for (const [key,value] of Object.entries(obj)){
console.log(key,value)
}
对象的浅拷贝
引用类型赋值只是传递内存地址
普通的
let obj2= obj1
达到的赋值操作只是将内存地址赋值给了obj2
,当obj1的对象发生变化的时候,obj2也会发生变化
1.开辟新的内存堆声明新的变量在进行赋值
let obj1={name:'xiaocao'}
let obj2={
name:obj1.name
}
2.先声明新的变量开启新的内存地址再通过循环进行值复制
let obj3={};
for(const key in obj){
obj3[key]=obj1[key]
}
3.通过assign()方法将对象压入新的对象中实现浅拷贝
let obj4=Object.assign({},obj1)
4.通过解构赋值的办法将源对象结构后赋值给新的对象
let obj5={...obj1}
对象的深拷贝
1.使用递归
let obj={
name:'xiaocao',
user:{
name:dacao
}
}
function copy(obj){
//对传入的对象是数组对象还是普通对象进行判断,防止源数组是数组对象的时候复制之后变成普通对象
let res=obj instanceof Array?[]:{};
for(const [key,value] of Object.entries(obj)){
//这里写出递归的结束条件,就是当源数据递归到了复制的对象是原始值类型时跳出递归并且将值复制给res,以达到深拷贝的目的
res[key]=typeof value=="object"?copy(value):value
}
return res;
}
let obj1=copy(obj);
//复制出来的新对象与源对象互不干扰
对象的属性特征
1.获取单个属性的信息
const user={
name:'xiaocao',
age:18
}
Object.getOwnPropertyDescriptor(user,"name")
/**
"name":{
"value":"xiaocao",//值
"writable":"true",//是否可以修改
"enumerable":"true",//是否可以遍历,或者可以通过Object.keys()读取
"configurable":"true",//是否可以被删除或者重新配置
}
*/
2.获取多个属性信息
Object.getOwnPropertyDescriptors(user)
3.操作对象属性
-
设置
Object.defineProperty(user,"name",{ value:"大曹", writable:false }); console.log(user.name)//大曹 //此时在严格模式下使用user.name="xiaocao"会报错,因为被修改成了不能被删除
-
封闭对象
Object.seal(user)
//封闭后对象所有属性的configurable变为false,不能删除,增加,修改对象属性 Object.isSealed(user) //是否封闭对象
-
冻结对象
Object.freeze(user)
冻结后writable:false,configurable:false,属性不能被增删改
4.使用访问器保护数据(属性操作实例)
const user={
data:{name:"xiaocao",age:10},
//设置访问器将年龄的修改限制在number类型并且在10-100岁之间
set age(value){
if(typeof value!="number"||value<10||value>100){
throw new Error('年龄格式错误');
}
this.data.age=value;
},
get age(){
return this.data.age+"岁";
}
};
//使用
user.age=999//不符合访问器条件,抛出异常"年龄格式错误"
console.log(user)
5.批量设置属性(实例)
const user={
name:'xiaocao',
url:"www.xiaocao.com",
get site(){
return `${this.name}的网站是${this.url}`;
},
set site(value){
[this.name,this.url]=value.split(",");
}
};
user.site="dacao,www.dacao.com";
console.log(user.site)
代理 Proxy
1.代理的语法和概念
概念:对象代理就是对整个对象进行控制
// 对象代理:对整个对象进行控制
const xs = {name : 'xiaocao'}
const proxy = new Proxy(xs,{
// 获取
get(obj, property){
return obj[property]
},
// 设置
set(obj, property, value){
obj[property] = value;
return true
}
});
proxy.name='new cao'
console.log(proxy.name)
2.控制函数
function a(num) {
return num == 1 ? 1 : num * a(num - 1);
}
let pro = new Proxy(a,{
apply(func, obj, args){
console.time("run")
func.apply(this,args)
console.timeEnd("run")
}
})
3.代理实现双向绑定
function View(){
// 代理实现双向绑定
/**
* 1.首先实现数据更新,设置一个init方法,监听数据更新时的操作
*/
let proxy = new Proxy({},{
get(obj,property){},
set(obj,property,value){
document
.querySelectorAll(`[v-model="${property}"]`)
.forEach(item => { item.value = value });
document
.querySelectorAll(`[v-bind="${property}"]`)
.forEach(item => { item.innerHTML = value });
return true
}
})
this.init = function(){
// 获取包含v-model属性的文本框
const els = document.querySelectorAll("[v-model]");
// 遍历该节点然后设置值value等于该属性节点的值实现dom双向绑定
els.forEach(item=>{
item.addEventListener("keyup",function(){
proxy[this.getAttribute("v-model")] = this.value;
})
})
}
}
new View().init()