浅析Object.defineProperty

157 阅读2分钟

defineProperty概述

根据es5中的描述该方法可以实现向对象添加属性,或修改现有属性的属性
-- 参数(obj对象,prop属性,descriptor配置项)
-- 配置项{
configurable?: boolean;
enumerable?: boolean;
value?: any; 默认值
writable?: boolean;
get?(): any;
set?(v: any): void;
}
es5文档中的解释如下图:

descriptor 配置项

配置项中value属性

  • 对象中仅有一个属性时
function defineProperty() {
    var _obj = {}
    Object.defineProperty(_obj, 'a', {  //返回定义的对象
        value: 1,
    })
    return _obj
}

var obj = defineProperty()
console.log(obj) //{a: 1}
  • 对象中有多个属性时
function defineProperties() {
    var _obj2 = {}
    Object.defineProperties(_obj2, {
        a: {
            value: 1
        },
        b: {
            value: 2,
            writable: true,
            enumerable: true,
            configurable: true
        }
    })
    return _obj2
}

var obj2 = defineProperties()
console.log(obj2) //Object {a: 1, b: 2}

配置项中writable属性

obj2.a = 3
obj2.b = 4
console.log("重写后", obj2)//重写后 {b: 4, a: 1} writable属性默认为不可写

配置项中enumerable属性

for (var k in obj2) {
    console.log("key值为", k) //key值为 b enumerable属性默认不可枚举
}

配置项中configurable属性

mdn中表述为:
configurable 当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为 false。 附上MDN地址:developer.mozilla.org/zh-CN/docs/…

delete obj2.a
delete obj2.b
console.log("删除后", obj2) //删除后 {a: 1} configurable属性默认false

配置项中get,set属性

function defineProperties() {
    var obj = {},
        a = 1,
        b = 3
    Object.defineProperties(obj, {
        a: {
            get() {
                return "读取到a的值为:" + a
            },
            set(newVal) { //对属性重新赋值时进行的操作
                console.log("设置a的值为:", newVal)
            }
        },
        b: {
            get() {
                return "读取到b的值为:" + b
            },
            set(newVal) {
                console.log("设置b的值为:", newVal)
            }
        }
    })//Object {a: 1, b: 2}

    return obj
}

var obj = defineProperties()
obj.a = 2//每次修改值的时候触发相应的set方法
obj.b = 4//每次修改值的时候触发相应的set方法
console.log(obj.a, obj.b)
//设置a的值为: 2
//设置b的值为: 4
//读取到a的值为:1 读取到b的值为:3

通过阻拦正常的数据操作,通过get,set方法重新设置即可称为数据劫持。

  • get,set方法存在时不能设置writable与value
function defineProperty() {
    var _obj = {},
    a = 1
    Object.defineProperty(_obj, 'a', {  //返回定义的对象
        value: 2,
        writable:true,
        get(){
            return a
        },
        set(newVal){
            console.log("设置值为:"+ newVal)
        }
    })
    return _obj
}

var obj = defineProperty()

出现报错