Object.defineproperty()用法详解

Posted by WWJ on July 12, 2018

Object.defineProperty

顾名思义,为对象定义属性

定义属性的方法

let person.name = 'wwj';
let person['name'] = 'wwj';
let Object.defineProperty(person, name, {
	value: 'wwj'
})

这样看起来Object.defineProperty定义属性的方法特别麻烦,那为什么还要使用这样的方法定义属性呢?

语法

Object.defineProperty(obj, propertyname, descriptor)

参数

  • obj:必需,你要在其上面添加属性,可以是用户自定义的对象,也可以是DOM对象;
  • propertyname:必需,属性名,是一个字符串类型的值;
  • descriptor:必需,属性描述符;

属性描述符

  • value:属性值,默认为undefined
let person = {};
Object.defineProperty(person, 'name', {
	value: 'wwj'
})
console.log(person.name) // wwj
  • configuable:如果为false,则任何尝试删除目标属性或修改属性以下特性(writable, configurable, enumerable)的行为将被无效化,直接在对象上定义的属性,这个属性该特性默认值为为 true
let person = {};
Object.defineProperty(person, 'name', {
	value: 'wwj',
	configurable: false
});
delete person.name;
console.log(person.name); // wwj
person.name = 'lingwu';
console.log(person.name); // wwj

// 直接在对象上定义的属性
let person = {};
person.name = 'wwj';
console.log(Object.getOwnPropertyDescriptor(person, 'name'))
// {value: "wwj", writable: true, enumerable: true, configurable: true}

//没有直接在对象上定义的属性,而是用defineProperty定义的属性,writable, configurable, enumerable这些特性都为false
let person = {};
Object.defineProperty(person, 'name', {
	value: 'wwj'
})
console.log(Object.getOwnPropertyDescriptor(person, 'name'))
// {value: "wwj", writable: false, enumerable: false, configurable: false}
  • enumerable:能否用for-in遍历出来或者用Object.keys()列举出来,对于直接在对象上定义的属性,这个特性默认为true
  • writable:该属性是否可写,如果设置成false,那么任何对属性的改写都无效;如果属性是直接被定义在对象上的话,那么这个属性就默认为true
let person = {}
Object.defineProperty(person, 'name', {
	value: 'wwj',
	writable: false
});
person.name = 'lingwu';
console.log(person.name); // wwj
  • set:一旦目标对象访问属性,就会调用这个方法,并返回结果,如果属性不存在该目标对象上,就会返回undefined
  • get:一旦目标对象设置该属性,就会调用这个方法。默认为undefined

实际应用(实现数据的双向绑定)

  1. 初级版demo
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <input type="text" id="txt">
    <p id="show_txt"></p>
    <script>
        let obj = {}
        Object.defineProperty(obj, 'txt', {
            get: function() {
                return obj;
            },
            set: function(newval) {
                document.getElementById('txt').value = newval;
                document.getElementById('show_txt').innerHTML = newval;
            }
        })
        document.addEventListener('keyup', function(e) {
            obj.txt = e.target.value;
        })
    </script>
</body>
</html>

vue的双向绑定源码之后再研究补充