7.Object.defineProperty以及数据代理(数据劫持)

1.Object.definePropery

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

备注:

        (1)应当直接在Object构造器对象上调用此方法,而不是在任意一个Object类型的实例

                上调用。

语法:

        Object.defineProperty(obj, prop, descriptor)

参数:

        obj:要定义属性的对象

        prop:要定义或修改的属性的名称或Symbol

        descriptor:要定义或修改的属性描述符

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

描述:

        该方法允许精确地添加或修改对象的属性。通过赋值操作添加的普通属性是可枚举的,

        在枚举对象属性时会被枚举到 (for...in或Object.keys方法),可以改变这些属性的值,

        也可以删除这些属性。这个方法允许修改默认的额外选项(或配置)。默认情况下,

        使用Object.defineProperty()添加的属性值是不可修改的。

        

描述符(descriptor):

        :

   

        (1) configurable(数据属性描述符、存取属性描述符公有):

        当且仅当该属性的configurable键值为true时,该属性的描述符才能够被改变,

        同时该属性也能从对应的对象上被删除。

        默认值: false

        (2) enumerable(数据属性描述符、存取属性描述符公有)

        当且仅当该属性的enumerable键值为true时,该属性才会出现在对象的枚举属性中。

        默认值:false

        当设置为false时,该对象中的属性无法被for...in和Object.keys枚举出来,其它方式能

        正常取值

        

        (3)  value(数据属性描述符)

        该属性对应的值。可以是任何有效的javaScript值(数值,对象,函数等)

        默认值:undefined

       

        (4) writable(数据属性描述符)

        当且仅当该属性的writable键值为true时,属性的值,也就是上面的value,才能

        被赋值运算符改变。

        默认值为false

        

        (5) get(存取属性描述符)

        属性的getter函数,如果没有getter,则为undefined。当访问该属性时,会调用此函数

        执行时不传入任何参数,但是会传入this对象(由于继承关系,这里的this并不一定是

        定义该属性的对象)。该函数的返回值会被用作属性的值

        默认为:undefined

        

        (6) set(存取属性描述符)

        属性的setter函数,如果没有setter,则为undefined。当属性值被修改时,会调用此函数

        该方法接受一个参数(也就是被赋予的新值),会传入赋值时的this对象。

        

验证Object.defineProperty描述符:

        value

        writable

        configurable

        enumerable

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
</body>
</html>
<script type="text/javascript">
    let number = 18
    let person = {
        age: 20
    }
    // 演示writable的默认值
    Object.defineProperty(person,'age', {
        value: 18, //默认值是undefined
        writable:false,//控制属性能否被修改,默认值是false
    })
    person.age = 30
    console.log("验证writable: false",person.age)

    // 演示enumerable
    Object.defineProperty(person,"age", {
        value: 18,
        enumerable: false, //控制属性能否被枚举
    })
    console.log("验证enumerable: false,通过console",person)
    for (let key in person) {
        // 枚举不了age
        console.log(`key:${key},value:${person[key]}`)
    }
    // 枚举不了age
    console.log("Object.keys(person)",Object.keys(person))

    // 演示configurable
    Object.defineProperty(person, "age", {
        configurable: false, //控制描述符能否被修改以及属性能否被删除
    })
    console.log("删除person对象中的age前",person)
    delete person.age
    console.log("删除person对象中的age后",person)
</script>

2.数据代理

数据代理,也叫数据劫持。指的是在访问或修改对象的某个属性时,通过一段代码拦截这个行为,进行额外的操作或者修改返回结果。比较典型的是Object.defineProperty()和ES2015中新增的Proxy对象。另外,还有已经被废弃的Object.observe(),废弃的原因正是Proxy的出现。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>何为数据代理</title>
	</head>
	<body>
		
	</body>
</html>
<script type="text/javascript" >
    let obj = {x:100}
    let obj2 = {y:200}
    /** 
        对obj2对象中的x属性进行数据劫持,实际我们使用了一个中间变量obj.x
        这是为了避免重复触发get
    */
    Object.defineProperty(obj2,'x',{
        get(){
            return obj.x
        },
        set(value){
            obj.x = value
        }
    })
    
    // 以下代码因为没有使用中间变量,当对obj3.x进行读取和赋值的操作时会报无限触发,报异常
    let obj3 = { x: 100 }
    Object.defineProperty(obj3,'x', {
        get() {
            return obj3.x
        },
        set(value) {
            obj3.x = value
        }
    })
</script>

当对obj3.x进行读取和赋值的操作时会报无限触发,报异常的测试

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值