学习js的第二十一天【proxy代理,深拷贝与浅拷贝】

1.Object.prototype.hasOwnProperty()对象,所有实例对象都可访问

方法:hasOwnProperty表示是否是对象自身的属性。
这个方法会查找一个对象是否有某个属性,但是不会去查找它的原型链

沿原型链上查找的方法不是它自身的

let obj = {
  name: jack,
  age:18
}
obj.hasOwnProperty('name')   //返回true
//hasOwnProperty表示是否是对象自身的属性.判断name是不是obj对象自身的属性

 2.Object.defineProperty()   是一个Object类对象的方法

作用:1>将对象的属性绑定到另一个对象上

let obj = {
				name: 'jack',
				age: 18,
			}
			let vm = {}
			// 将obj对象的所有属性动态添加到vm对象上

			//1. 遍历obj对象
			for (const key in obj) {
				// 2. 动态给vm添加属性
				Object.defineProperty(vm, key, {
					// vm.name
					get() {
						return obj[key]
					},
                    // vm.name = 'rose'
					set(newValue) {
						// 原值与新值相同直接返回
						if (obj[key] == newValue) {
							return
						}
						obj[key] = newValue // 设置属性新值
					},
				})
			}

  2>实现数据劫持:监听对象数据变化,实现数据变化自动更新界面

 <div>
        <p class="title"></p>
    </div>
    <script>
        let obj = {
            name: 'jack',
            age: 18,
        }
        let vm = {}
        //将obj对象的所有属性动态添加到vm对象上
        //1.遍历对象
        for (const key in obj) {
            //2.动态给vm添加属性
            Object.defineProperty(vm, key, {
                get() {
                    console.log('get')
                    return obj[key]
                },
                set(newValue) {
                    //原值与新值相同直接返回
                    if (obj[key] == newValue) {
                        return
                    }
                    obj[key] = newValue //设置属性新值
                    console.log('set')
                    //监听对象数据变化后执行其他操作
                    //更新界面
                    const titleEle = document.querySelector('.title')
                    titleEle.innerHTML = obj.name+' '+obj.age
                },
            })
        }

语法:Object.defineProperty(obj, 'name',{})

方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

let obj={}
Object.defineProperty(obj,'name',{   //动态添加name
   value:'jack',
   configurable:true,   //允许删除属性
   writable:true,   //允许修改属性
   enumerable:true,  //允许遍历对象})
console.log(obj.name)

属性:

1.数据属性:configurable:true,   //允许删除属性
                     writable:true,   //允许修改属性
                     enumerable:true,  //允许遍历对象

2.访问器属性:

1.get:在读取属性时调用的函数,默认值是undefined

let obj={}
Oject.defineProperty(obj,'age',{
 get:function(){
        return 20}
console.log(obj.age)    //输出值为20  //obj访问age时会自动调用get方法

2..set:在写入属性的时候调用的函数,默认值是undefined

set(newValue){
  obj.age=18     //修改属性值时,set自动调用
}
console.log(obj.age)   //输出为18

proxy代理:

1.不直接对对象、函数或者数组进行操作,而是把它挂载到Proxy(代理)上,直接对代理的做一系列操作。

2.代理是使用 Proxy 构造函数创建的。这个构造函数接收两个参数:目标对象和处理程序对象。缺少其中任何一个参数都会抛出 TypeError。

let obj={
     name:'jack',
     age:18
}
let handler={}   //处理程序
let proxyObj= new Proxy (obj,handler)    //代理对象
proxyObj.name='rose'    //通过代理对象操作目标对象
function test1() {
				// 目标对象
				let obj = {
					name: 'jack',
					age: 18,
				}
				// 处理程序
				let handler = {}
				// 代理对象
				let proxyObj = new Proxy(obj, handler)

				// 通过代理对象操作目标对象和直接操作目标对象是一样的效果,

				console.log('obj.name ', obj.name)
				console.log('proxyObj.name ', proxyObj.name)

				proxyObj.name = 'rose' // 通过代理对象更改目标对象属性值
				console.log('obj.name ', obj.name)
			}

捕获器:

1.get捕获器,get()

通过代理对象获取目标对象属性值时触发

                    // get(){

                    //     return '这是代理给的新值'

                    // }

2.set捕获器,set()

// 通过代理对象给属性设置值触发

// 通过代理对象操作目标对象时,可以对目标对象做一些拦截操作, 在处理程序handler中设置
            // 目标对象
				let obj = {
					name: 'jack',
					age: 18,
				}
				// 处理程序
				let handler = {
                    // 通过代理对象获取目标对象属性值时触发
                    // get(){
                    //     return '这是代理给的新值'
                    // }
                    // get参数
                    get(target,propery,receiver){
                        console.log('target ',target)
                        console.log('propery ',propery)
                        console.log('receiver ',receiver)
                        return target[propery]
                    },
                    // 通过代理对象给属性设置值触发
                    set(target,propery,value,receiver){
                        console.log('set >>>');
                        console.log('target ',target)
                        console.log('propery ',propery)
                        console.log('value ',value)
                        console.log('receiver ',receiver)
                        target[propery] = value
                    }
                }
				// 代理对象
				let proxyObj = new Proxy(obj, handler)
                // console.log( proxyObj.age )
                proxyObj.age = 20

通过Proxy代理目标对象obj,实现数据劫持-通过代理对象proxy改变目标对象属性值时,在get,set捕获器方法中做一些处理, 比如更新界面

 <div></div>

  
        let obj = {
            message:''
        }
        let proxyObj = new Proxy(obj,{
            get(target,propery){
                return target[propery]
            },
            set(target,propery,value){
                target[propery] = value // 通过代理对象改变目标对象属性值
                // 更新界面操作-更改div内容
                document.querySelector('div').innerHTML = value
            }
        })

        proxyObj.message = 'hello'

深拷贝和浅拷贝:

1.浅拷贝:复制的obj对象只复制一层,如果对象属性值是对象则不能复制

2.深拷贝:完全复制的obj对象,如果对象属性值是对象一起复制得到全新对象

 实现方式:

1.展开运算符{…obj},实现浅拷贝
缺点:只能拷贝一层,如果属性值是对象,无法拷贝

let obj = {
					name: 'jack',
					age: 18,
					fun: {
						swiming: '游泳',
					},
				}
			    let newObj = { ...obj } // 浅拷贝,如果属性值是对象不能拷贝
                newObj.name = 'rose'
                newObj.fun.swiming = '打游戏'

                console.log('newObj :',newObj.name,  '  oldObj :',obj.name);
                console.log('newObj fun :',newObj.fun.swiming,  '  oldObj  fun :',obj.fun.swiming);
                console.dir(newObj);
                console.dir(obj);

2.JSON.parse(JSON.stringify(obj))
缺点: 数据类型是Function或数据值为undefined无法拷贝

let str = JSON.stringify(obj)  //obj->str

可以将对象转成JSON字符串

注:对象只能是Object形式对象不是Math,Date

 let newObj = JSON.parse(str)  // str->obj

可以将JSON字符串转成对象

let objStr = JSON.stringify(obj)
				console.log(obj)
				console.log(objStr, typeof objStr)

				let str = '{"num":1001,"score":98}'
				let obj1 = JSON.parse(str)
				console.log(obj1)
				console.log(obj1.num)

利用JSON实现深拷贝:

​
let obj = {
				name: 'jack',
				age: 18,
				fun: {
					swiming: '游泳',
				},
                say:function(){
                    console.log('说话');
                },
                score:undefined
			}
            // 利用JSON实现深拷贝
            // let str = JSON.stringify(obj)  //obj->str
            // let newObj = JSON.parse(str)  // str->obj
            let newObj = JSON.parse(JSON.stringify(obj))
            newObj.name = 'rose'
            newObj.age = 20
            newObj.fun.swiming = '玩游戏'

            console.dir(newObj)

            console.dir(obj)

​

递归 cloneDeep(),实现深拷贝,解决JSON深拷贝问题

let newObj = Array.isArray(obj)? []:{} // 存储拷贝的原对象属性方法
                for(const key in obj){
                    if(obj[key] && typeof obj[key] === 'object'){
                        newObj[key] = cloneObj(obj[key])
                    }else{
                        newObj[key] = obj[key]
                    }
                }
                return newObj
            }

			let obj = {
				name: 'jack',
				age: 18,
				fun: {
					swiming: '游泳',
				},
				say: function () {
					console.log('说话')
				},
				score: undefined,
			}

            let newObj = cloneObj(obj)

            newObj.name = 'rose'
            newObj.age = 20
            newObj.score = 98
            newObj.fun.swiming = '玩游戏'

            console.dir(newObj)
            console.dir(obj)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值