Vue 理解数据代理 object.defineProperty

2023-12-21 16:07:57

要想理解数据代理就需要对object.defineProperty这个方法特别熟。这个方法在object身上,名字叫做defineProperty,这个方法可不要小瞧,vue底层很多地方都使用到了。

比如vue里面使用的数据劫持就使用到了这个方法,数据代理用到了这个方法,后面计算属性也使用到了这个方法。

给对象添加属性

这个defineProperty就是给一个对象添加属性使用的,或者说给一个对象定义属性用的。

这里传入三个参数,第一个是给哪个对象添加属性,第二个添加的属性叫做什么名字,最后就是一个特别重要的参数叫做配置项,配置项里面可以写很多的配置

其实你在person对象里面直接添加age属性就行了,但是这种方式没有defineProperty方法高级。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>

<body>
        
    <script type="text/javascript">
       //定义对象
       let person = {
        name: "zhangsan",
        sex: "male"
       }
    //现在想要张山有年龄,添加一个属性age 18
    Object.defineProperty(person,'age',{
        value: 18  //这样person对象就有了age这个属性,并且是18
    })
    console.log(person)
    //添加了这个属性,但是不参与遍历,也就是不可以枚举
    //这个方法可以将传入对象里面的所有属性名提取出来变成数组
    console.log(Object.keys(person))

   //for i in既可以遍历数组,也可以遍历对象
    for(i in person){
        console.log(i)
    }
    </script>

</body>

</html>

enumerable: true? 控制属性是否可以枚举,默认值是false

如果属性可以遍历那就需要借助另外一个配置项了,?enumerable,这样虽然可以遍历了,但是需要修改该属性值还是修改不了的。?

writable: true? 可以修改属性值? ?configurable: true??可以删除属性值

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>

<body>
        
    <script type="text/javascript">
       //定义对象
       let person = {
        name: "zhangsan",
        sex: "male"
       }
    //现在想要张山有年龄,添加一个属性age 18
    Object.defineProperty(person,'age',{
        value: 18,  //这样person对象就有了age这个属性,并且是18
        enumerable: true, //控制属性是否可以被枚举,默认值是false
        writable: true,  //控制属性是否可以被修改,默认值是false
        configurable: true //控制属性是否可以被删除,默认值false        
    })
    
    person.age = 19
    console.log(person.age)
    console.log(delete person.age)

    console.log(Object.keys(person))
    for(i in person){
        console.log(i)
    }
    </script>

</body>

</html>

上面方法和四个配置项看起来复杂,但是可以对追加的配置项的属性进行很多高级的限制,比如能不能修改,能不能删除,能不能枚举。

---------------------------------------------------------------------------------------------------------------------------------

上面都是基本的配置项,其实还可以传高级的配置项。

现在需要让person对象有一个age属性,age属性保存年龄,并且它的数值是读取num变量读取出来的,而不是自己定义的,并且这个age的值的变化跟着num变量一起变化。

这里就需要借助defineProperty,这里面能够写一个配置,配置的名称叫做get,值是一个函数。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>

<body>
        
    <script type="text/javascript">
        let num = 19
       //定义对象
       let person = {
        name: "zhangsan",
        sex: "male"
       }
    //现在想要张山有年龄,添加一个属性age 18
    Object.defineProperty(person,'age',{
       // value: 18,  //这样person对象就有了age这个属性,并且是18
       // enumerable: true, //控制属性是否可以被枚举,默认值是false
       // writable: true,  //控制属性是否可以被修改,默认值是false
        //configurable: true //控制属性是否可以被删除,默认值false

        //当有人读取person的age属性时候,get函数(getter)就会被调用,返回值就是age的值
        get(){
            console.log("有人读取了age属性")
            return num
        },
        //当有人修改person的age属性时候,set函数(setter)就会被调用,且会收到修改的具体值
        set(value){
            console.log("有人修改了age属性且值是",value)
            num = value
        }
        
    })
    
    person.age = 19
    console.log(person.age)
    console.log(delete person.age)


    console.log(Object.keys(person))
    for(i in person){
        console.log(i)
    }
    </script>

</body>

</html>

有没有一种感觉,person和num其实是两个东西,借助defineProperty让其产生关联。得有这种体会,person确实是一个对象,确实有age属性,但是值现用,我们也现取,取靠get,要改就调用set,并且将值给你拿过来。(这个get和set是非常重要的)

?

?

数据代理的定义


通过一个对象代理另外一个对象中属性的操作(读写)。

有个对象obj,它有一个属性是x,想访问就obj.x,或者obj.x=xxx直接赋值就行。

现在有obj2,希望让obj2也能够访问到obj.x,也希望obj2以后能够修改这个x,这就是通过一个对象obj2,代理另外一个对象obj中属性的操作。

下面就是最简单的数据代理:obj1可以操作自身的x,但是obj2可以通过数据代理操作obj1的x,这就高级了,这就是数据代理。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>

<body>      
    <script type="text/javascript">
    
       //定义对象
       let obj1 = {
        x: 100       
       }
       let obj2 = {
        y: 200       
       }

       //想通过obj2能够读取到x并且可以进行修改
       //操作对象为obj2,追加一个属性叫做x
       Object.defineProperty(obj2,'x',{
        //以后有人试图读取obj2.x属性值的时候,给它的是obj1.x的属性值
        get(){
          alert("读取obj2的x属性了")
          return obj1.x
        },
        //有人想更改obj2的x属性值,那么就更改obj1.x的值即可
        set(value){
          alert("修改obj2的x属性了")
          obj1.x = value
          console.log("修改之后obj2.x值为:" + obj2.x)
        }
       })       
    </script>
</body>
</html>

文章来源:https://blog.csdn.net/qq_34556414/article/details/134942863
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。