【js第20天——对象详解与深浅拷贝】

目录

前言

一、对象方法Object.prototype.hasOwnProperty()

二、构造函数类方法Object.defineProperty()

 1.构造函数类方法Object.defineProperty()

 2.属性描述对象:descriptor

 1)数据属性

2)访问器属性

3.构造函数类方法Object.defineProperty()的作用示例

1)动态将对象属性绑定到另一个对象上

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

三、Proxy代理

1.什么是代理

2.JS代理Proxy

3.捕获器(trap)

1)get捕获器

2)set捕获器

4.Proxy代理应用

四、深拷贝和浅拷贝

 1.深拷贝和浅拷贝

2.实现深浅拷贝的方式 

1)展开运算符...obj实现浅拷贝

          2)JSON.parse(JSON.stringify(obj))实现深拷贝 

          3)递归 cloneDeep()实现深拷贝


前言

今天我们主要学习对象详解,主要介绍处理对象三个方法,原型对象上的方法Object.prototype.hasOwnProperty(),构造函数类方法Object.defineProperty() ,Proxy代理,以及在面试中经常问到的深浅拷贝。


一、对象方法Object.prototype.hasOwnProperty()

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

应用:

通过原型链继承该方法

判断属性是否是对象自身的

语法:

let 引用变量=实例对象.hasOwnProperty(属性或方法)

代码如下:(示例) 

let obj = {
				name: 'jack',
				age: 18,
			}
            Object.prototype.score = 100
            
			// 判断属性age是否是对象obj的
			// let isOk = obj.hasOwnProperty('name')
            console.log('obj.score ',obj.score)

			let isOk = obj.hasOwnProperty('score')
			console.log('isOk ', isOk)

            let arr = []
            console.dir(arr)
            console.dir(Array.prototype);
            console.log(arr.hasOwnProperty('length') )
            console.log(arr.hasOwnProperty('find') )

二、构造函数类方法Object.defineProperty()

 1.构造函数类方法Object.defineProperty()

作用:①将对象属性绑定到另一个对象上

②数据劫持-监听对象数据变化,实现数据变化自动更新界面

方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
语法 :
    Object.defineProperty(obj, prop, descriptor)
参数
  obj : 要定义属性的对象。
  prop:要定义或修改的属性的名称或 Symbol 。
  descriptor:要定义或修改的属性描述符对象。

返回值
    被传递给函数的对象。

2.属性描述对象:descriptor

   1)数据属性

①configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性,默认值为false。

②enumerable:表示能否通过for in循环访问属性,默认值为false

③writable:表示能否修改属性的值。默认值为false。

④value:包含这个属性的数据值。默认值为undefined。

代码如下:(示例) 

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

				 delete obj.name  // 删除对象属性
				 obj.name = 'rose' // 修改对象属性值
				console.log(obj.name)

2)访问器属性

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

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

 代码如下:(示例) 

let obj = {}
                Object.defineProperty(obj,'age',{
                    // 访问对象age属性时自动调用  obj.age
                    get:function(){
                        console.log('get >>>> ')
                        return 20
                    },
                    // 赋值给对象属性age时自动调用并赋值
                    set(newValue){
                        // this.age = newValue
                        console.log('set >>>> ')
                    }
                })
                console.log('111',obj.age)
                obj.age = 18
                console.log('222',obj.age)

3.构造函数类方法Object.defineProperty()的作用示例

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)数据劫持-监听对象数据变化,实现数据变化自动更新界面

 代码如下:(示例) 

<p class="title">jack</p>
    <script>
        let obj={
            name:'jack',
            age:18
        }
        let vw={}
        for(const key in obj){
           Object.defineProperty(vw,key,{
            get(){
                return obj[key]
            },
            set(newValue){
                if(obj[key] === newValue){
                    return
                }
                obj[key]=newValue

                //动态改变p内容
                const titleEle=document.querySelector('.title')
                titleEle.innerHTML=obj.name 
            }
           })
        }
       
    </script>

三、Proxy代理

1.什么是代理

简单理解就是我们不直接对对象、函数或者数组进行操作,而是把它挂载到Proxy(代理)上,
直接对代理的做一系列操作。我们去买房,房产中介就相当于我们的代理,我们不需要直接向卖家沟通。

2.JS代理Proxy

代理是目标对象的抽象。目标对象既可以直接被操作,也可以通过代理来操作。 但直接操作会绕过代理施予的行为。
首先就是空代理,就是什么也不做,在代理对象上执行的所有操作都会无障碍地传播到目标对象。
代理是使用 Proxy 构造函数创建的。这个构造函数接收两个参数:目标对象和处理程序对象。缺少其中任何一个参数都会抛出 TypeError。

 通过代理对象操作目标对象时,可以对目标对象做一些拦截操作, 在处理程序handler中设置,这就要使用到捕获器(trap)

3.捕获器(trap)

使用代理的主要目的是可以定义捕获器(trap)。捕获器就是在处理程序对象中定义的“基本操作的“拦截器”。
每个处理程序对象可以包含零个或多个捕获器,每个捕获器都对应一种基本操作,可以直接 或间接在代理对象上调用。每次在代理对象上调用这些基本操作时,代理可以在这些操作传播到目标对 象之前先调用捕获器函数,从而拦截并修改相应的行为

捕获器一共13种
apply 、construct、defineProperty、deleteProperty、
get、getOwnPropertyDescriptor、getPrototypeOf、has、isExtensible
ownKeys、preventExtensions、set、setPrototypeOf
 

接下来我们主要介绍get与set两种捕获器

1)get捕获器

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

 get参数:get(target,propery,receiver){  }

target:目标对象           propery:属性        receiver:处理程序    

2)set捕获器

set捕获器通过代理对象给属性设置值触发

 set参数:set(target,propery,value,receiver){  }

target:目标对象           propery:属性       value:设置的新值       receiver:处理程序    

4.Proxy代理应用

通过Proxy代理目标对象obj,实现数据劫持-通过代理对象proxy改变目标对象属性值时,

在get,set捕获器方法中做一些处理, 比如更新界面

 代码如下:(示例) 

<div></div>
    
    <script>
        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'
    </script>

四、深拷贝和浅拷贝

 1.深拷贝和浅拷贝

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

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

深拷贝和浅拷贝内存图:

深拷贝:

 浅拷贝:

2.实现深浅拷贝的方式 

1)展开运算符...obj实现浅拷贝

缺点:只能拷贝一层,如果属性值是对象,无法拷贝

代码如下:(示例) 

let obj = {
            name: 'jack',
            age: 21,
            score: 98,
            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(obj)
        console.dir(newObj)

运行结果:

2)JSON.parse(JSON.stringify(obj))实现深拷贝 

JSON对象

JSON.stringify(obj)

obj -> 字符串

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

'{name:"jack",age:18,fun:{swiming:"游泳"}}' <- JSON字符串

JSON.parse(str)

字符串 -> obj

注: 字符串必须 是 json格式

代码如下:(示例) 

 let obj = {
            name: 'jack',
            age: 21,
            score: 98,
            fun: {
                swiming: '游泳'

            }
        }
        let newobj=JSON.parse(JSON.stringify(obj))
        newobj.fun.swiming='打游戏'
        newobj.age=20
        console.dir(obj)
        console.dir(newobj)

运行结果:

 3)递归 cloneDeep()实现深拷贝

代码如下:(示例) 

let obj = {
            name: 'jack',
            age: 21,
            score: 98,
            fun: {
                swiming: '游泳'

            }
        }
        function cloneobj(obj){
            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 newObj = cloneobj(obj)
        newObj.fun.swiming='打游戏'
        newObj.age=25
        console.dir(obj)
        console.dir(newObj)

运行结果:


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值